CnC_Remastered_Collection

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

IRANDOM.CPP (5390B)


      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  **   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   **
     18  ***************************************************************************
     19  *                                                                         *
     20  *                 Project Name : LIBRARY                                  *
     21  *                                                                         *
     22  *                    File Name : IRANDOM.C                                *
     23  *                                                                         *
     24  *                   Programmer : Barry W. Green                           *
     25  *                                                                         *
     26  *                  Last Update : 10 Feb, 1995     [BWG]                   *
     27  *                                                                         *
     28  *-------------------------------------------------------------------------*
     29  * Functions:                                                              *
     30  * - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - */
     31 
     32 #include <stdlib.h>
     33 #include <time.h>
     34 #include "misc.h"
     35 
     36 
     37 
     38 extern "C" unsigned long RandNumb = 0x12349876;
     39 
     40 
     41 
     42 /* IRANDOM ----------------------------------------------------------
     43 
     44    IRandom returns a random value between min and max inclusive.
     45 
     46    INPUTS:	int min and int max
     47 
     48    RETURNS:	int random number
     49 */
     50 
     51 int IRandom(int minval, int maxval)
     52 {
     53 	int num,mask;
     54 
     55 	// Keep minval and maxval straight.
     56 	if (minval > maxval) {
     57 		minval ^= maxval;
     58 		maxval ^= minval;
     59 		minval ^= maxval;
     60 	}
     61 
     62 	mask = Get_Random_Mask(maxval - minval);
     63 
     64 	while( (num = (rand() & mask) + minval) > maxval ) ;
     65 	return(num);
     66 }
     67 
     68 
     69 
     70 unsigned char Random(void)
     71 {
     72 	__asm {
     73 		lea	esi, [RandNumb]		//; get offset in segment of RandNumb
     74 		xor	eax,eax
     75 		mov	al,[esi]
     76 		shr	al,1						//; shift right 1 bit (bit0 in carry)
     77 		shr	al,1
     78 		rcl	[BYTE PTR esi+2],1	//; rcl byte 3 of RandNumb
     79 		rcl	[BYTE PTR esi+1],1 	//; rcl byte 2 of RandNumb
     80 		cmc								//; complement carry
     81 		sbb	al,[esi]					//; sbb byte 1 of RandNumb
     82 		shr	al,1						//; sets carry
     83 		rcr	[BYTE PTR esi],1 		//; rcr byte 1 of RandNumb
     84 		mov	al,[esi]					//; reload byte 1 of RandNumb
     85 		xor	al,[esi+1]				//; xor with byte 2 of RandNumb
     86 	}
     87 }		 
     88 
     89 
     90 
     91 int Get_Random_Mask(int maxval)
     92 {
     93 	__asm {
     94 		
     95 		bsr	ecx,[maxval]		//	; put bit position of highest bit in ecx
     96 		mov	eax, 1				//	; set one bit on in eax
     97 		jz		invalid				//	; if BSR shows maxval==0, return eax=1
     98 		inc	ecx					// ; get one bit higher than count showed
     99 		shl	eax,cl				// ; move our EAX bit into position
    100 		dec	eax					// ; dec it to create the mask.
    101 invalid:
    102 	}
    103 }
    104 
    105 
    106 
    107 			  
    108 #if (0)
    109 
    110 RandNumb	DD	12349876H
    111 
    112 ;
    113 ; UBYTE Random(VOID);
    114 ; int Get_Random_Mask(int maxval);
    115 ;
    116 ; ----------------------------------------------------------------
    117 
    118 ;-----------------------------------------------------------------
    119 ; RANDOM
    120 ;
    121 ; UBYTE Random(VOID);
    122 ;
    123 ;*
    124 
    125 	PROC	Random C near
    126 	USES	esi
    127 
    128 	lea	esi, [RandNumb]		; get offset in segment of RandNumb
    129 	xor	eax,eax
    130 	mov	al,[esi]
    131 	shr	al,1			; shift right 1 bit (bit0 in carry)
    132 	shr	al,1
    133 	rcl	[BYTE PTR esi+2],1	; rcl byte 3 of RandNumb
    134 	rcl	[BYTE PTR esi+1],1 	; rcl byte 2 of RandNumb
    135 	cmc				; complement carry
    136 	sbb	al,[esi]		; sbb byte 1 of RandNumb
    137 	shr	al,1			; sets carry
    138 	rcr	[BYTE PTR esi],1 	; rcr byte 1 of RandNumb
    139 	mov	al,[esi]		; reload byte 1 of RandNumb
    140 	xor	al,[esi+1]		; xor with byte 2 of RandNumb
    141 
    142 	ret
    143 
    144 	ENDP	Random
    145 
    146 
    147 ;-----------------------------------------------------------------
    148 ; GET_RANDOM_MASK - returns an AND value that is large enough that it
    149 ; encloses the 'maxval' parameter.
    150 ;
    151 ; int Get_Random_Mask(int maxval);
    152 ;
    153 ;*
    154 
    155 	PROC	Get_Random_Mask C near
    156 	USES	ecx
    157 	ARG	maxval:DWORD
    158 
    159 ; This function takes as a parameter a maximum value, for example, 61.  It
    160 ; then tries to create an AND mask that is big enough to enclose that number.
    161 ; For our example case, that AND mask would be 0x3F.  It does this by scanning
    162 ; for the highest bit in the number, then making an all-1's mask from that
    163 ; bit position down to bit 0.
    164 	bsr	ecx,[maxval]		; put bit position of highest bit in ecx
    165 	mov	eax,1			; set one bit on in eax
    166 	jz	??invalid		; if BSR shows maxval==0, return eax=1
    167 	inc	ecx			; get one bit higher than count showed
    168 	shl	eax,cl			; move our EAX bit into position
    169 	dec	eax			; dec it to create the mask.
    170 ??invalid:
    171 	ret
    172 	ENDP	Get_Random_Mask
    173 ;----------------------------------------------------------------------------
    174 
    175 	END
    176 #endif