MiscAsm.cpp (43256B)
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 17 /* 18 ** 19 ** Misc. assembly code moved from headers 20 ** 21 ** 22 ** 23 ** 24 ** 25 */ 26 27 #include "FUNCTION.H" 28 29 30 31 extern "C" void __cdecl Mem_Copy(void const *source, void *dest, unsigned long bytes_to_copy) 32 { 33 memcpy(dest, source, bytes_to_copy); 34 } 35 36 37 /*********************************************************************************************** 38 * Distance -- Determines the lepton distance between two coordinates. * 39 * * 40 * This routine is used to determine the distance between two coordinates. It uses the * 41 * Dragon Strike method of distance determination and thus it is very fast. * 42 * * 43 * INPUT: coord1 -- First coordinate. * 44 * * 45 * coord2 -- Second coordinate. * 46 * * 47 * OUTPUT: Returns the lepton distance between the two coordinates. * 48 * * 49 * WARNINGS: none * 50 * * 51 * HISTORY: * 52 * 05/27/1994 JLB : Created. * 53 *=============================================================================================*/ 54 int Distance_Coord(COORDINATE coord1, COORDINATE coord2) 55 { 56 __asm { 57 mov eax,[coord1] 58 mov ebx,[coord2] 59 mov dx,ax 60 sub dx,bx 61 jg okx 62 neg dx 63 okx: 64 shr eax,16 65 shr ebx,16 66 sub ax,bx 67 jg oky 68 neg ax 69 oky: 70 cmp ax,dx 71 jg ok 72 xchg ax,dx 73 ok: 74 shr dx,1 75 add ax,dx 76 } 77 } 78 79 80 81 82 /* 83 ;*************************************************************************** 84 ;* DESIRED_FACING16 -- Converts coordinates into a facing number. * 85 ;* * 86 ;* This converts coordinates into a desired facing number that ranges * 87 ;* from 0 to 15 (0 equals North and going clockwise). * 88 ;* * 89 ;* INPUT: x1,y1 -- Position of origin point. * 90 ;* * 91 ;* x2,y2 -- Position of target. * 92 ;* * 93 ;* OUTPUT: Returns desired facing as a number from 0 to 255 but * 94 ;* accurate to 22.5 degree increments. * 95 ;* * 96 ;* WARNINGS: If the two coordinates are the same, then -1 will be * 97 ;* returned. It is up to you to handle this case. * 98 ;* * 99 ;* HISTORY: * 100 ;* 08/14/1991 JLB : Created. * 101 ;*=========================================================================* 102 */ 103 104 long __cdecl Desired_Facing16(long x1, long y1, long x2, long y2) 105 { 106 static const char _new_facing16[] = { 107 3, 2, 4,-1, 1, 2,0,-1, 108 13,14,12,-1,15,14,0,-1, 109 5, 6, 4,-1, 7, 6,8,-1, 110 11,10,12,-1, 9,10,8,-1 111 }; 112 113 114 __asm { 115 xor ebx,ebx //; Index byte (built). 116 117 //; Determine Y axis difference. 118 mov edx,[y1] 119 mov ecx,[y2] 120 sub edx,ecx //; DX = Y axis (signed). 121 jns short absy 122 inc ebx //; Set the signed bit. 123 neg edx //; ABS(y) 124 absy: 125 126 //; Determine X axis difference. 127 shl ebx,1 128 mov eax,[x1] 129 mov ecx,[x2] 130 sub ecx,eax //; CX = X axis (signed). 131 jns short absx 132 inc ebx //; Set the signed bit. 133 neg ecx //; ABS(x) 134 absx: 135 136 //; Determine the greater axis. 137 cmp ecx,edx 138 jb short dxisbig 139 xchg ecx,edx 140 dxisbig: 141 rcl ebx,1 //; Y > X flag bit. 142 143 //; Determine the closeness or farness of lesser axis. 144 mov eax,edx 145 inc eax //; Round up. 146 shr eax,1 147 inc eax //; Round up. 148 shr eax,1 //; 1/4 of greater axis. 149 150 cmp ecx,eax 151 rcl ebx,1 //; Very close to major axis bit. 152 153 sub edx,eax 154 cmp edx,ecx 155 rcl ebx,1 //; Very far from major axis bit. 156 157 xor eax,eax 158 mov al,[_new_facing16+ebx] 159 160 //; Normalize to 0..FF range. 161 shl eax,4 162 163 // ret 164 } 165 } 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 /* 182 ;*************************************************************************** 183 ;* Desired_Facing256 -- Desired facing algorithm 0..255 resolution. * 184 ;* * 185 ;* This is a desired facing algorithm that has a resolution of 0 * 186 ;* through 255. * 187 ;* * 188 ;* INPUT: srcx,srcy -- Source coordinate. * 189 ;* * 190 ;* dstx,dsty -- Destination coordinate. * 191 ;* * 192 ;* OUTPUT: Returns with the desired facing to face the destination * 193 ;* coordinate from the position of the source coordinate. North * 194 ;* is 0, East is 64, etc. * 195 ;* * 196 ;* WARNINGS: This routine is slower than the other forms of desired * 197 ;* facing calculation. Use this routine when accuracy is * 198 ;* required. * 199 ;* * 200 ;* HISTORY: * 201 ;* 12/24/1991 JLB : Adapted. * 202 ;*=========================================================================*/ 203 204 int __cdecl Desired_Facing256(LONG srcx, LONG srcy, LONG dstx, LONG dsty) 205 { 206 207 __asm { 208 xor ebx,ebx //; Facing number. 209 210 ////; Determine absolute X delta and left/right direction. 211 mov ecx,[dstx] 212 sub ecx,[srcx] 213 jge short xnotneg 214 neg ecx 215 mov ebx,11000000b //; Set bit 7 and 6 for leftward. 216 xnotneg: 217 218 //; Determine absolute Y delta and top/bottom direction. 219 mov eax,[srcy] 220 sub eax,[dsty] 221 jge short ynotneg 222 xor ebx,01000000b //; Complement bit 6 for downward. 223 neg eax 224 ynotneg: 225 226 //; Set DX=64 for quadrants 0 and 2. 227 mov edx,ebx 228 and edx,01000000b 229 xor edx,01000000b 230 231 //; Determine if the direction is closer to the Y axis and make sure that 232 //; CX holds the larger of the two deltas. This is in preparation for the 233 //; divide. 234 cmp eax,ecx 235 jb short gotaxis 236 xchg eax,ecx 237 xor edx,01000000b //; Closer to Y axis so make DX=64 for quad 0 and 2. 238 gotaxis: 239 240 //; If closer to the X axis then add 64 for quadrants 0 and 2. If 241 //; closer to the Y axis then add 64 for quadrants 1 and 3. Determined 242 //; add value is in DX and save on stack. 243 push edx 244 245 //; Make sure that the division won't overflow. Reduce precision until 246 //; the larger number is less than 256 if it appears that an overflow 247 //; will occur. If the high byte of the divisor is not zero, then this 248 //; guarantees no overflow, so just abort shift operation. 249 test eax,0FFFFFF00h 250 jnz short nooverflow 251 again: 252 test ecx,0FFFFFF00h 253 jz short nooverflow 254 shr ecx,1 255 shr eax,1 256 jmp short again 257 nooverflow: 258 259 //; Make sure that the division won't underflow (divide by zero). If 260 //; this would occur, then set the quotient to $FF and skip divide. 261 or ecx,ecx 262 jnz short nounderflow 263 mov eax,0FFFFFFFFh 264 jmp short divcomplete 265 266 //; Derive a pseudo angle number for the octant. The angle is based 267 //; on $00 = angle matches long axis, $00 = angle matches $FF degrees. 268 nounderflow: 269 xor edx,edx 270 shld edx,eax,8 //; shift high byte of eax into dl 271 shl eax,8 272 div ecx 273 divcomplete: 274 275 //; Integrate the 5 most significant bits into the angle index. If DX 276 //; is not zero, then it is 64. This means that the dividend must be negated 277 //; before it is added into the final angle value. 278 shr eax,3 279 pop edx 280 or edx,edx 281 je short noneg 282 dec edx 283 neg eax 284 noneg: 285 add eax,edx 286 add eax,ebx 287 and eax,0FFH 288 // ret 289 } 290 } 291 292 293 294 295 296 297 298 299 300 301 302 303 /* 304 305 ;*************************************************************************** 306 ;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S ** 307 ;*************************************************************************** 308 ;* * 309 ;* Project Name : Support Library * 310 ;* * 311 ;* File Name : FACING8.ASM * 312 ;* * 313 ;* Programmer : Joe L. Bostic * 314 ;* * 315 ;* Start Date : May 8, 1991 * 316 ;* * 317 ;* Last Update : February 6, 1995 [BWG] * 318 ;* * 319 ;*-------------------------------------------------------------------------* 320 ;* Functions: * 321 ;* Desired_Facing8 -- Determines facing to reach a position. * 322 ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * 323 324 325 IDEAL 326 P386 327 MODEL USE32 FLAT 328 329 GLOBAL C Desired_Facing8 :NEAR 330 ; INCLUDE "wwlib.i" 331 332 DATASEG 333 334 ; 8 direction desired facing lookup table. Build the index according 335 ; to the following bits: 336 ; 337 ; bit 3 = Is y2 < y1? 338 ; bit 2 = Is x2 < x1? 339 ; bit 1 = Is the ABS(x2-x1) < ABS(y2-y1)? 340 ; bit 0 = Is the facing closer to a major axis? 341 //NewFacing8 DB 1,2,1,0,7,6,7,0,3,2,3,4,5,6,5,4 342 343 // CODESEG 344 */ 345 346 /* 347 ;*************************************************************************** 348 ;* DESIRED_FACING8 -- Determines facing to reach a position. * 349 ;* * 350 ;* This routine will return with the most desirable facing to reach * 351 ;* one position from another. It is accurate to a resolution of 0 to * 352 ;* 7. * 353 ;* * 354 ;* INPUT: x1,y1 -- Position of origin point. * 355 ;* * 356 ;* x2,y2 -- Position of target. * 357 ;* * 358 ;* OUTPUT: Returns desired facing as a number from 0..255 with an * 359 ;* accuracy of 32 degree increments. * 360 ;* * 361 ;* WARNINGS: If the two coordinates are the same, then -1 will be * 362 ;* returned. It is up to you to handle this case. * 363 ;* * 364 ;* HISTORY: * 365 ;* 07/15/1991 JLB : Documented. * 366 ;* 08/08/1991 JLB : Same position check. * 367 ;* 08/14/1991 JLB : New algorithm * 368 ;* 02/06/1995 BWG : Convert to 32-bit * 369 ;*=========================================================================* 370 */ 371 int __cdecl Desired_Facing8(long x1, long y1, long x2, long y2) 372 { 373 374 static const char _new_facing8[] = {1,2,1,0,7,6,7,0,3,2,3,4,5,6,5,4}; 375 376 __asm { 377 378 xor ebx,ebx //; Index byte (built). 379 380 //; Determine Y axis difference. 381 mov edx,[y1] 382 mov ecx,[y2] 383 sub edx,ecx //; DX = Y axis (signed). 384 jns short absy 385 inc ebx //; Set the signed bit. 386 neg edx //; ABS(y) 387 absy: 388 389 //; Determine X axis difference. 390 shl ebx,1 391 mov eax,[x1] 392 mov ecx,[x2] 393 sub ecx,eax //; CX = X axis (signed). 394 jns short absx 395 inc ebx //; Set the signed bit. 396 neg ecx //; ABS(x) 397 absx: 398 399 //; Determine the greater axis. 400 cmp ecx,edx 401 jb short dxisbig 402 xchg ecx,edx 403 dxisbig: 404 rcl ebx,1 //; Y > X flag bit. 405 406 //; Determine the closeness or farness of lesser axis. 407 mov eax,edx 408 inc eax //; Round up. 409 shr eax,1 410 411 cmp ecx,eax 412 rcl ebx,1 //; Close to major axis bit. 413 414 xor eax,eax 415 mov al,[_new_facing8+ebx] 416 417 //; Normalize to 0..FF range. 418 shl eax,5 419 420 // ret 421 422 } 423 424 } 425 426 427 428 #if (0) 429 430 /* 431 ; $Header: //depot/Projects/Mobius/QA/Project/Run/SOURCECODE/TIBERIANDAWN/MiscAsm.cpp#139 $ 432 ;*************************************************************************** 433 ;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S ** 434 ;*************************************************************************** 435 ;* * 436 ;* Project Name : Support Library * 437 ;* * 438 ;* File Name : FACING16.ASM * 439 ;* * 440 ;* Programmer : Joe L. Bostic * 441 ;* * 442 ;* Start Date : May 8, 1991 * 443 ;* * 444 ;* Last Update : February 6, 1995 [BWG] * 445 ;* * 446 ;*-------------------------------------------------------------------------* 447 ;* Functions: * 448 ;* Desired_Facing16 -- Converts coordinates into a facing number. * 449 ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * 450 451 452 IDEAL 453 P386 454 MODEL USE32 FLAT 455 456 GLOBAL C Desired_Facing16 :NEAR 457 ; INCLUDE "wwlib.i" 458 459 DATASEG 460 461 ; 16 direction desired facing lookup table. Build the index according 462 ; to the following bits: 463 ; 464 ; bit 4 = Is y2 < y1? 465 ; bit 3 = Is x2 < x1? 466 ; bit 2 = Is the ABS(x2-x1) < ABS(y2-y1)? 467 ; bit 1 = Is the lesser absolute difference very close to zero? 468 ; bit 0 = Is the lesser absolute difference very close to the greater dist? 469 NewFacing16 DB 3, 2, 4,-1, 1, 2,0,-1 470 DB 13,14,12,-1,15,14,0,-1 471 DB 5, 6, 4,-1, 7, 6,8,-1 472 DB 11,10,12,-1, 9,10,8,-1 473 474 CODESEG 475 476 ;*************************************************************************** 477 ;* DESIRED_FACING16 -- Converts coordinates into a facing number. * 478 ;* * 479 ;* This converts coordinates into a desired facing number that ranges * 480 ;* from 0 to 15 (0 equals North and going clockwise). * 481 ;* * 482 ;* INPUT: x1,y1 -- Position of origin point. * 483 ;* * 484 ;* x2,y2 -- Position of target. * 485 ;* * 486 ;* OUTPUT: Returns desired facing as a number from 0 to 255 but * 487 ;* accurate to 22.5 degree increments. * 488 ;* * 489 ;* WARNINGS: If the two coordinates are the same, then -1 will be * 490 ;* returned. It is up to you to handle this case. * 491 ;* * 492 ;* HISTORY: * 493 ;* 08/14/1991 JLB : Created. * 494 ;*=========================================================================* 495 */ 496 long __cdecl Desired_Facing16(long x1, long y1, long x2, long y2) 497 { 498 499 __asm { 500 xor ebx,ebx ; Index byte (built). 501 502 ; Determine Y axis difference. 503 mov edx,[y1] 504 mov ecx,[y2] 505 sub edx,ecx //; DX = Y axis (signed). 506 jns short absy 507 inc ebx //; Set the signed bit. 508 neg edx //; ABS(y) 509 absy: 510 511 //; Determine X axis difference. 512 shl ebx,1 513 mov eax,[x1] 514 mov ecx,[x2] 515 sub ecx,eax //; CX = X axis (signed). 516 jns short absx 517 inc ebx //; Set the signed bit. 518 neg ecx //; ABS(x) 519 absx: 520 521 //; Determine the greater axis. 522 cmp ecx,edx 523 jb short dxisbig 524 xchg ecx,edx 525 dxisbig: 526 rcl ebx,1 //; Y > X flag bit. 527 528 //; Determine the closeness or farness of lesser axis. 529 mov eax,edx 530 inc eax //; Round up. 531 shr eax,1 532 inc eax //; Round up. 533 shr eax,1 //; 1/4 of greater axis. 534 535 cmp ecx,eax 536 rcl ebx,1 //; Very close to major axis bit. 537 538 sub edx,eax 539 cmp edx,ecx 540 rcl ebx,1 //; Very far from major axis bit. 541 542 xor eax,eax 543 mov al,[NewFacing16+ebx] 544 545 //; Normalize to 0..FF range. 546 shl eax,4 547 548 // ret 549 } 550 } 551 552 553 554 555 #if (0) 556 PROC Desired_Facing16 C near 557 USES ebx, ecx, edx 558 559 ARG x1:DWORD 560 ARG y1:DWORD 561 ARG x2:DWORD 562 ARG y2:DWORD 563 564 xor ebx,ebx ; Index byte (built). 565 566 ; Determine Y axis difference. 567 mov edx,[y1] 568 mov ecx,[y2] 569 sub edx,ecx ; DX = Y axis (signed). 570 jns short ??absy 571 inc ebx ; Set the signed bit. 572 neg edx ; ABS(y) 573 ??absy: 574 575 ; Determine X axis difference. 576 shl ebx,1 577 mov eax,[x1] 578 mov ecx,[x2] 579 sub ecx,eax ; CX = X axis (signed). 580 jns short ??absx 581 inc ebx ; Set the signed bit. 582 neg ecx ; ABS(x) 583 ??absx: 584 585 ; Determine the greater axis. 586 cmp ecx,edx 587 jb short ??dxisbig 588 xchg ecx,edx 589 ??dxisbig: 590 rcl ebx,1 ; Y > X flag bit. 591 592 ; Determine the closeness or farness of lesser axis. 593 mov eax,edx 594 inc eax ; Round up. 595 shr eax,1 596 inc eax ; Round up. 597 shr eax,1 ; 1/4 of greater axis. 598 599 cmp ecx,eax 600 rcl ebx,1 ; Very close to major axis bit. 601 602 sub edx,eax 603 cmp edx,ecx 604 rcl ebx,1 ; Very far from major axis bit. 605 606 xor eax,eax 607 mov al,[NewFacing16+ebx] 608 609 ; Normalize to 0..FF range. 610 shl eax,4 611 612 ret 613 614 ENDP Desired_Facing16 615 616 END 617 #endif 618 #endif 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 /* 636 ;*********************************************************************************************** 637 ;* Cardinal_To_Fixed -- Converts cardinal numbers into a fixed point number. * 638 ;* * 639 ;* This utility function will convert cardinal numbers into a fixed point fraction. The * 640 ;* use of fixed point numbers occurs throughout the product -- since it is a convenient * 641 ;* tool. The fixed point number is based on the formula: * 642 ;* * 643 ;* result = cardinal / base * 644 ;* * 645 ;* The accuracy of the fixed point number is limited to 1/256 as the lowest and up to * 646 ;* 256 as the largest. * 647 ;* * 648 ;* INPUT: base -- The key number to base the fraction about. * 649 ;* * 650 ;* cardinal -- The other number (hey -- what do you call it?) * 651 ;* * 652 ;* OUTPUT: Returns with the fixed point number of the "cardinal" parameter as it relates * 653 ;* to the "base" parameter. * 654 ;* * 655 ;* WARNINGS: none * 656 ;* * 657 ;* HISTORY: * 658 ;* 02/17/1995 BWG : Created. * 659 ;*=============================================================================================*/ 660 661 unsigned int __cdecl Cardinal_To_Fixed(unsigned base, unsigned cardinal) 662 { 663 __asm { 664 665 mov eax,0FFFFh //; establish default return value 666 667 mov ebx,[base] 668 or ebx, ebx 669 jz retneg1 //; if base==0, return 65535 670 671 mov eax,[cardinal] //; otherwise, return (cardinal*256)/base 672 shl eax,8 673 xor edx,edx 674 div ebx 675 676 retneg1: 677 //ret 678 679 680 } 681 } 682 683 #if (0) 684 PROC Cardinal_To_Fixed C near 685 USES ebx, edx 686 687 ARG base:DWORD 688 ARG cardinal:DWORD 689 690 mov eax,0FFFFh ; establish default return value 691 692 mov ebx,[base] 693 or ebx,ebx 694 jz near ??retneg1 ; if base==0, return 65535 695 696 mov eax,[cardinal] ; otherwise, return (cardinal*256)/base 697 shl eax,8 698 xor edx,edx 699 div ebx 700 701 ??retneg1: 702 ret 703 704 ENDP Cardinal_To_Fixed 705 #endif 706 707 /* 708 ;*********************************************************************************************** 709 ;* Fixed_To_Cardinal -- Converts a fixed point number into a cardinal number. * 710 ;* * 711 ;* Use this routine to convert a fixed point number into a cardinal number. * 712 ;* * 713 ;* INPUT: base -- The base number that the original fixed point number was created from. * 714 ;* * 715 ;* fixed -- The fixed point number to convert. * 716 ;* * 717 ;* OUTPUT: Returns with the reconverted number. * 718 ;* * 719 ;* WARNINGS: none * 720 ;* * 721 ;* HISTORY: * 722 ;* 02/17/1995 BWG : Created. * 723 ;*=============================================================================================*/ 724 725 unsigned int __cdecl Fixed_To_Cardinal(unsigned base, unsigned fixed) 726 { 727 // PROC Fixed_To_Cardinal C near 728 // USES edx 729 730 // ARG base:DWORD 731 // ARG fixed:DWORD 732 733 __asm { 734 mov eax,[base] 735 mul [fixed] 736 add eax,080h //; eax = (base * fixed) + 0x80 737 738 test eax,0FF000000h //; if high byte set, return FFFF 739 jnz rneg1 740 shr eax,8 //; else, return eax/256 741 jmp all_done 742 rneg1: 743 mov eax,0FFFFh //; establish default return value 744 all_done: 745 //ret 746 } 747 748 749 #if (0) 750 mov eax,[base] 751 mul [fixed] 752 add eax,080h ; eax = (base * fixed) + 0x80 753 754 test eax,0FF000000h ; if high byte set, return FFFF 755 jnz ??rneg1 756 shr eax,8 ; else, return eax/256 757 ret 758 ??rneg1 : 759 mov eax,0FFFFh ; establish default return value 760 ret 761 762 ENDP Fixed_To_Cardinal 763 764 END 765 #endif 766 767 768 } 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 void __cdecl Set_Bit(void * array, int bit, int value) 785 { 786 __asm { 787 mov ecx, [bit] 788 mov eax, [value] 789 mov esi, [array] 790 mov ebx,ecx 791 shr ebx,5 792 and ecx,01Fh 793 btr [esi+ebx*4],ecx 794 or eax,eax 795 jz ok 796 bts [esi+ebx*4],ecx 797 ok: 798 } 799 } 800 801 802 int __cdecl Get_Bit(void const * array, int bit) 803 { 804 __asm { 805 mov eax, [bit] 806 mov esi, [array] 807 mov ebx,eax 808 shr ebx,5 809 and eax,01Fh 810 bt [esi+ebx*4],eax 811 setc al 812 } 813 } 814 815 int __cdecl First_True_Bit(void const * array) 816 { 817 __asm { 818 mov esi, [array] 819 mov eax,-32 820 again: 821 add eax,32 822 mov ebx,[esi] 823 add esi,4 824 bsf ebx,ebx 825 jz again 826 add eax,ebx 827 } 828 } 829 830 831 int __cdecl First_False_Bit(void const * array) 832 { 833 __asm { 834 835 mov esi, [array] 836 mov eax,-32 837 again: 838 add eax,32 839 mov ebx,[esi] 840 not ebx 841 add esi,4 842 bsf ebx,ebx 843 jz again 844 add eax,ebx 845 } 846 } 847 848 int __cdecl Bound(int original, int min, int max) 849 { 850 __asm { 851 mov eax,[original] 852 mov ebx,[min] 853 mov ecx,[max] 854 cmp ebx,ecx 855 jl okorder 856 xchg ebx,ecx 857 okorder: cmp eax,ebx 858 jg okmin 859 mov eax,ebx 860 okmin: cmp eax,ecx 861 jl okmax 862 mov eax,ecx 863 okmax: 864 } 865 } 866 867 868 869 870 871 872 873 874 875 CELL __cdecl Coord_Cell(COORDINATE coord) 876 { 877 __asm { 878 mov eax, coord 879 mov ebx,eax 880 shr eax,010h 881 xor al,al 882 shr eax,2 883 or al,bh 884 } 885 886 } 887 888 889 890 891 892 893 894 895 896 /* 897 ;*********************************************************** 898 ; SHAKE_SCREEN 899 ; 900 ; VOID Shake_Screen(int shakes); 901 ; 902 ; This routine shakes the screen the number of times indicated. 903 ; 904 ; Bounds Checking: None 905 ; 906 ;* 907 */ 908 void __cdecl Shake_Screen(int shakes) 909 { 910 // PG_TO_FIX 911 // Need a different solution for shaking the screen 912 shakes; 913 } 914 915 916 917 #if (0) 918 GLOBAL C Shake_Screen :NEAR 919 920 CODESEG 921 922 ;*********************************************************** 923 ; SHAKE_SCREEN 924 ; 925 ; VOID Shake_Screen(int shakes); 926 ; 927 ; This routine shakes the screen the number of times indicated. 928 ; 929 ; Bounds Checking: None 930 ; 931 ;* 932 PROC Shake_Screen C near 933 USES ecx, edx 934 935 ARG shakes:DWORD 936 ret 937 938 mov ecx,[shakes] 939 940 ;;; push es 941 ;;; mov ax,40h 942 ;;; mov es,ax 943 ;;; mov dx,[es:63h] 944 ;;; pop es 945 mov eax,[0463h] ; get CRTC I/O port 946 mov dx,ax 947 add dl,6 ; video status port 948 949 ??top_loop: 950 951 ??start_retrace: 952 in al,dx 953 test al,8 954 jz ??start_retrace 955 956 ??end_retrace: 957 in al,dx 958 test al,8 959 jnz ??end_retrace 960 961 cli 962 sub dl,6 ; dx = 3B4H or 3D4H 963 964 mov ah,01 ; top word of start address 965 mov al,0Ch 966 out dx,al 967 xchg ah,al 968 inc dx 969 out dx,al 970 xchg ah,al 971 dec dx 972 973 mov ah,040h ; bottom word = 40 (140h) 974 inc al 975 out dx,al 976 xchg ah,al 977 inc dx 978 out dx,al 979 xchg ah,al 980 981 sti 982 add dl,5 983 984 ??start_retrace2: 985 in al,dx 986 test al,8 987 jz ??start_retrace2 988 989 ??end_retrace2: 990 in al,dx 991 test al,8 992 jnz ??end_retrace2 993 994 ??start_retrace3: 995 in al,dx 996 test al,8 997 jz ??start_retrace3 998 999 ??end_retrace3: 1000 in al,dx 1001 test al,8 1002 jnz ??end_retrace3 1003 1004 cli 1005 sub dl,6 ; dx = 3B4H or 3D4H 1006 1007 mov ah,0 1008 mov al,0Ch 1009 out dx,al 1010 xchg ah,al 1011 inc dx 1012 out dx,al 1013 xchg ah,al 1014 dec dx 1015 1016 mov ah,0 1017 inc al 1018 out dx,al 1019 xchg ah,al 1020 inc dx 1021 out dx,al 1022 xchg ah,al 1023 1024 sti 1025 add dl,5 1026 1027 loop ??top_loop 1028 1029 ret 1030 1031 ENDP Shake_Screen 1032 1033 ;*********************************************************** 1034 1035 END 1036 1037 #endif 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 /* 1053 1054 ;*************************************************************************** 1055 ;* Conquer_Build_Fading_Table -- Builds custom shadow/light fading table. * 1056 ;* * 1057 ;* This routine is used to build a special fading table for C&C. There * 1058 ;* are certain colors that get faded to and cannot be faded again. * 1059 ;* With this rule, it is possible to draw a shadow multiple times and * 1060 ;* not have it get any lighter or darker. * 1061 ;* * 1062 ;* INPUT: palette -- Pointer to the 768 byte IBM palette to build from. * 1063 ;* * 1064 ;* dest -- Pointer to the 256 byte remap table. * 1065 ;* * 1066 ;* color -- Color index of the color to "fade to". * 1067 ;* * 1068 ;* frac -- The fraction to fade to the specified color * 1069 ;* * 1070 ;* OUTPUT: Returns with pointer to the remap table. * 1071 ;* * 1072 ;* WARNINGS: none * 1073 ;* * 1074 ;* HISTORY: * 1075 ;* 10/07/1992 JLB : Created. * 1076 ;*=========================================================================*/ 1077 1078 void * __cdecl Conquer_Build_Fading_Table(void const *palette, void *dest, int color, int frac) 1079 { 1080 /* 1081 global C Conquer_Build_Fading_Table : NEAR 1082 PROC Conquer_Build_Fading_Table C near 1083 USES ebx, ecx, edi, esi 1084 1085 ARG palette:DWORD 1086 ARG dest:DWORD 1087 ARG color:DWORD 1088 ARG frac:DWORD 1089 1090 LOCAL matchvalue:DWORD ; Last recorded match value. 1091 LOCAL targetred:BYTE ; Target gun red. 1092 LOCAL targetgreen:BYTE ; Target gun green. 1093 LOCAL targetblue:BYTE ; Target gun blue. 1094 LOCAL idealred:BYTE 1095 LOCAL idealgreen:BYTE 1096 LOCAL idealblue:BYTE 1097 LOCAL matchcolor:BYTE ; Tentative match color. 1098 1099 ALLOWED_COUNT EQU 16 1100 ALLOWED_START EQU 256-ALLOWED_COUNT 1101 */ 1102 1103 #define ALLOWED_COUNT 16 1104 #define ALLOWED_START 256-ALLOWED_COUNT 1105 1106 int matchvalue = 0; //:DWORD ; Last recorded match value. 1107 unsigned char targetred = 0; //BYTE ; Target gun red. 1108 unsigned char targetgreen = 0; //BYTE ; Target gun green. 1109 unsigned char targetblue = 0; //BYTE ; Target gun blue. 1110 unsigned char idealred = 0; //BYTE 1111 unsigned char idealgreen = 0; //BYTE 1112 unsigned char idealblue = 0; //BYTE 1113 unsigned char matchcolor = 0; //:BYTE ; Tentative match color. 1114 1115 __asm { 1116 1117 cld 1118 1119 ; If the source palette is NULL, then just return with current fading table pointer. 1120 cmp [palette],0 1121 je fini1 1122 cmp [dest],0 1123 je fini1 1124 1125 ; Fractions above 255 become 255. 1126 mov eax,[frac] 1127 cmp eax,0100h 1128 jb short ok 1129 mov [frac],0FFh 1130 ok: 1131 1132 ; Record the target gun values. 1133 mov esi,[palette] 1134 mov ebx,[color] 1135 add esi,ebx 1136 add esi,ebx 1137 add esi,ebx 1138 lodsb 1139 mov [targetred],al 1140 lodsb 1141 mov [targetgreen],al 1142 lodsb 1143 mov [targetblue],al 1144 1145 ; Main loop. 1146 xor ebx,ebx ; Remap table index. 1147 1148 ; Transparent black never gets remapped. 1149 mov edi,[dest] 1150 mov [edi],bl 1151 inc edi 1152 1153 ; EBX = source palette logical number (1..255). 1154 ; EDI = running pointer into dest remap table. 1155 mainloop: 1156 inc ebx 1157 mov esi,[palette] 1158 add esi,ebx 1159 add esi,ebx 1160 add esi,ebx 1161 1162 mov edx,[frac] 1163 shr edx,1 1164 ; new = orig - ((orig-target) * fraction); 1165 1166 lodsb ; orig 1167 mov dh,al ; preserve it for later. 1168 sub al,[targetred] ; al = (orig-target) 1169 imul dl ; ax = (orig-target)*fraction 1170 shl eax,1 1171 sub dh,ah ; dh = orig - ((orig-target) * fraction) 1172 mov [idealred],dh ; preserve ideal color gun value. 1173 1174 lodsb ; orig 1175 mov dh,al ; preserve it for later. 1176 sub al,[targetgreen] ; al = (orig-target) 1177 imul dl ; ax = (orig-target)*fraction 1178 shl eax,1 1179 sub dh,ah ; dh = orig - ((orig-target) * fraction) 1180 mov [idealgreen],dh ; preserve ideal color gun value. 1181 1182 lodsb ; orig 1183 mov dh,al ; preserve it for later. 1184 sub al,[targetblue] ; al = (orig-target) 1185 imul dl ; ax = (orig-target)*fraction 1186 shl eax,1 1187 sub dh,ah ; dh = orig - ((orig-target) * fraction) 1188 mov [idealblue],dh ; preserve ideal color gun value. 1189 1190 ; Sweep through a limited set of existing colors to find the closest 1191 ; matching color. 1192 1193 mov eax,[color] 1194 mov [matchcolor],al ; Default color (self). 1195 mov [matchvalue],-1 ; Ridiculous match value init. 1196 mov ecx,ALLOWED_COUNT 1197 1198 mov esi,[palette] ; Pointer to original palette. 1199 add esi,(ALLOWED_START)*3 1200 1201 ; BH = color index. 1202 mov bh,ALLOWED_START 1203 innerloop: 1204 1205 xor edx,edx ; Comparison value starts null. 1206 1207 ; Build the comparison value based on the sum of the differences of the color 1208 ; guns squared. 1209 lodsb 1210 sub al,[idealred] 1211 mov ah,al 1212 imul ah 1213 add edx,eax 1214 1215 lodsb 1216 sub al,[idealgreen] 1217 mov ah,al 1218 imul ah 1219 add edx,eax 1220 1221 lodsb 1222 sub al,[idealblue] 1223 mov ah,al 1224 imul ah 1225 add edx,eax 1226 jz short perfect ; If perfect match found then quit early. 1227 1228 cmp edx,[matchvalue] 1229 jae short notclose 1230 mov [matchvalue],edx ; Record new possible color. 1231 mov [matchcolor],bh 1232 notclose: 1233 inc bh ; Checking color index. 1234 loop innerloop 1235 mov bh,[matchcolor] 1236 perfect: 1237 mov [matchcolor],bh 1238 xor bh,bh ; Make BX valid main index again. 1239 1240 ; When the loop exits, we have found the closest match. 1241 mov al,[matchcolor] 1242 stosb 1243 cmp ebx,ALLOWED_START-1 1244 jne mainloop 1245 1246 ; Fill the remainder of the remap table with values 1247 ; that will remap the color to itself. 1248 mov ecx,ALLOWED_COUNT 1249 fillerloop: 1250 inc bl 1251 mov al,bl 1252 stosb 1253 loop fillerloop 1254 1255 fini1: 1256 mov esi,[dest] 1257 mov eax,esi 1258 1259 //ret 1260 } 1261 } 1262 1263 1264 1265 1266 1267 1268 extern "C" long __cdecl Reverse_Long(long number) 1269 { 1270 __asm { 1271 mov eax,dword ptr [number] 1272 xchg al,ah 1273 ror eax,16 1274 xchg al,ah 1275 } 1276 } 1277 1278 1279 extern "C" short __cdecl Reverse_Short(short number) 1280 { 1281 __asm { 1282 mov ax,[number] 1283 xchg ah,al 1284 } 1285 } 1286 1287 1288 1289 extern "C" long __cdecl Swap_Long(long number) 1290 { 1291 __asm { 1292 mov eax,dword ptr [number] 1293 ror eax,16 1294 } 1295 } 1296 1297 1298 1299 1300 1301 1302 1303 1304 /* 1305 1306 1307 1308 ;*************************************************************************** 1309 ;* strtrim -- Remove the trailing white space from a string. * 1310 ;* * 1311 ;* Use this routine to remove white space characters from the beginning * 1312 ;* and end of the string. The string is modified in place by * 1313 ;* this routine. * 1314 ;* * 1315 ;* INPUT: buffer -- Pointer to the string to modify. * 1316 ;* * 1317 ;* OUTPUT: none * 1318 ;* * 1319 ;* WARNINGS: none * 1320 ;* * 1321 ;* HISTORY: * 1322 ;* 10/07/1992 JLB : Created. * 1323 ;*=========================================================================* 1324 ; VOID cdecl strtrim(BYTE *buffer); 1325 global C strtrim :NEAR 1326 PROC strtrim C near 1327 USES ax, edi, esi 1328 1329 ARG buffer:DWORD ; Pointer to string to modify. 1330 */ 1331 void __cdecl strtrim(char *buffer) 1332 { 1333 __asm { 1334 cmp [buffer],0 1335 je short fini 1336 1337 ; Prepare for string scanning by loading pointers. 1338 cld 1339 mov esi,[buffer] 1340 mov edi,esi 1341 1342 ; Strip white space from the start of the string. 1343 looper: 1344 lodsb 1345 cmp al,20h ; Space 1346 je short looper 1347 cmp al,9 ; TAB 1348 je short looper 1349 stosb 1350 1351 ; Copy the rest of the string. 1352 gruntloop: 1353 lodsb 1354 stosb 1355 or al,al 1356 jnz short gruntloop 1357 dec edi 1358 ; Strip the white space from the end of the string. 1359 looper2: 1360 mov [edi],al 1361 dec edi 1362 mov ah,[edi] 1363 cmp ah,20h 1364 je short looper2 1365 cmp ah,9 1366 je short looper2 1367 1368 fini: 1369 //ret 1370 } 1371 } 1372 1373 1374 /* 1375 ;*************************************************************************** 1376 ;* Fat_Put_Pixel -- Draws a fat pixel. * 1377 ;* * 1378 ;* Use this routine to draw a "pixel" that is bigger than 1 pixel * 1379 ;* across. This routine is faster than drawing a similar small shape * 1380 ;* and faster than calling Fill_Rect. * 1381 ;* * 1382 ;* INPUT: x,y -- Screen coordinates to draw the pixel's upper * 1383 ;* left corner. * 1384 ;* * 1385 ;* color -- The color to render the pixel in. * 1386 ;* * 1387 ;* size -- The number of pixels width of the big "pixel". * 1388 ;* * 1389 ;* page -- The pointer to a GraphicBuffer class or something * 1390 ;* * 1391 ;* OUTPUT: none * 1392 ;* * 1393 ;* WARNINGS: none * 1394 ;* * 1395 ;* HISTORY: * 1396 ;* 03/17/1994 JLB : Created. * 1397 ;*=========================================================================* 1398 ; VOID cdecl Fat_Put_Pixel(long x, long y, long color, long size, void *page) 1399 global C Fat_Put_Pixel:NEAR 1400 PROC Fat_Put_Pixel C near 1401 USES eax, ebx, ecx, edx, edi, esi 1402 1403 ARG x:DWORD ; X coordinate of upper left pixel corner. 1404 ARG y:DWORD ; Y coordinate of upper left pixel corner. 1405 ARG color:DWORD ; Color to use for the "pixel". 1406 ARG siz:DWORD ; Size of "pixel" to plot (square). 1407 ARG gpage:DWORD ; graphic page address to plot onto 1408 */ 1409 1410 void __cdecl Fat_Put_Pixel(int x, int y, int color, int siz, GraphicViewPortClass &gpage) 1411 { 1412 __asm { 1413 1414 cmp [siz],0 1415 je short exit_label 1416 1417 ; Set EDI to point to start of logical page memory. 1418 ;*=================================================================== 1419 ; Get the viewport information and put bytes per row in ecx 1420 ;*=================================================================== 1421 mov ebx,[gpage] ; get a pointer to viewport 1422 mov edi,[ebx]GraphicViewPortClass.Offset ; get the correct offset 1423 1424 ; Verify the the Y pixel offset is legal. 1425 mov eax,[y] 1426 cmp eax,[ebx]GraphicViewPortClass.Height ;YPIXEL_MAX 1427 jae short exit_label 1428 mov ecx,[ebx]GraphicViewPortClass.Width 1429 add ecx,[ebx]GraphicViewPortClass.XAdd 1430 add ecx,[ebx]GraphicViewPortClass.Pitch 1431 mul ecx 1432 add edi,eax 1433 1434 ; Verify the the X pixel offset is legal. 1435 1436 mov edx,[ebx]GraphicViewPortClass.Width 1437 cmp edx,[x] 1438 mov edx,ecx 1439 jbe short exit_label 1440 add edi,[x] 1441 1442 ; Write the pixel to the screen. 1443 mov ebx,[siz] ; Copy of pixel size. 1444 sub edx,ebx ; Modulo to reach start of next row. 1445 mov eax,[color] 1446 again: 1447 mov ecx,ebx 1448 rep stosb 1449 add edi,edx ; EDI points to start of next row. 1450 dec [siz] 1451 jnz short again 1452 1453 exit_label: 1454 //ret 1455 } 1456 } 1457 1458 1459 1460 1461 1462 1463 1464 1465 1466 1467 1468 /* 1469 ;*************************************************************************** 1470 ;** C O N F I D E N T I A L --- W E S T W O O D A S S O C I A T E S ** 1471 ;*************************************************************************** 1472 ;* * 1473 ;* Project Name : Westwood Library * 1474 ;* * 1475 ;* File Name : CRC.ASM * 1476 ;* * 1477 ;* Programmer : Joe L. Bostic * 1478 ;* * 1479 ;* Start Date : June 12, 1992 * 1480 ;* * 1481 ;* Last Update : February 10, 1995 [BWG] * 1482 ;* * 1483 ;*-------------------------------------------------------------------------* 1484 ;* Functions: * 1485 ;* - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - * 1486 1487 IDEAL 1488 P386 1489 MODEL USE32 FLAT 1490 1491 GLOBAL C Calculate_CRC :NEAR 1492 1493 CODESEG 1494 */ 1495 1496 extern "C" long __cdecl Calculate_CRC(void *buffer, long length) 1497 { 1498 unsigned long crc; 1499 1500 unsigned long local_length = (unsigned long) length; 1501 1502 __asm { 1503 ; Load pointer to data block. 1504 mov [crc],0 1505 pushad 1506 mov esi,[buffer] 1507 cld 1508 1509 ; Clear CRC to default (NULL) value. 1510 xor ebx,ebx 1511 1512 //; Fetch the length of the data block to CRC. 1513 1514 mov ecx,[local_length] 1515 1516 jecxz short fini 1517 1518 ; Prepare the length counters. 1519 mov edx,ecx 1520 and dl,011b 1521 shr ecx,2 1522 1523 ; Perform the bulk of the CRC scanning. 1524 jecxz short remainder2 1525 accumloop: 1526 lodsd 1527 rol ebx,1 1528 add ebx,eax 1529 loop accumloop 1530 1531 ; Handle the remainder bytes. 1532 remainder2: 1533 or dl,dl 1534 jz short fini 1535 mov ecx,edx 1536 xor eax,eax 1537 1538 and ecx,0FFFFh 1539 push ecx 1540 nextbyte: 1541 lodsb 1542 ror eax,8 1543 loop nextbyte 1544 pop ecx 1545 neg ecx 1546 add ecx,4 1547 shl ecx,3 1548 ror eax,cl 1549 1550 ;nextbyte: 1551 ; shl eax,8 1552 ; lodsb 1553 ; loop nextbyte 1554 rol ebx,1 1555 add ebx,eax 1556 1557 fini: 1558 mov [crc],ebx 1559 popad 1560 mov eax,[crc] 1561 //ret 1562 } 1563 } 1564 1565 1566 1567 1568 1569 1570 extern "C" void __cdecl Set_Palette_Range(void *palette) 1571 { 1572 if (palette == NULL) { 1573 return; 1574 } 1575 1576 memcpy(CurrentPalette, palette, 768); 1577 Set_DD_Palette(palette); 1578 }