CnC_Remastered_Collection

Command and Conquer: Red Alert
Log | Files | Refs | README | LICENSE

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 }