CnC_Remastered_Collection

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

IRANDOM.CPP (5392B)


      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 
    109 
    110 
    111 
    112 
    113 
    114 
    115 #if (0)
    116 
    117 RandNumb	DD	12349876H
    118 
    119 ;
    120 ; UBYTE Random(VOID);
    121 ; int Get_Random_Mask(int maxval);
    122 ;
    123 ; ----------------------------------------------------------------
    124 
    125 ;-----------------------------------------------------------------
    126 ; RANDOM
    127 ;
    128 ; UBYTE Random(VOID);
    129 ;
    130 ;*
    131 
    132 	PROC	Random C near
    133 	USES	esi
    134 
    135 	lea	esi, [RandNumb]		; get offset in segment of RandNumb
    136 	xor	eax,eax
    137 	mov	al,[esi]
    138 	shr	al,1			; shift right 1 bit (bit0 in carry)
    139 	shr	al,1
    140 	rcl	[BYTE PTR esi+2],1	; rcl byte 3 of RandNumb
    141 	rcl	[BYTE PTR esi+1],1 	; rcl byte 2 of RandNumb
    142 	cmc				; complement carry
    143 	sbb	al,[esi]		; sbb byte 1 of RandNumb
    144 	shr	al,1			; sets carry
    145 	rcr	[BYTE PTR esi],1 	; rcr byte 1 of RandNumb
    146 	mov	al,[esi]		; reload byte 1 of RandNumb
    147 	xor	al,[esi+1]		; xor with byte 2 of RandNumb
    148 
    149 	ret
    150 
    151 	ENDP	Random
    152 
    153 
    154 ;-----------------------------------------------------------------
    155 ; GET_RANDOM_MASK - returns an AND value that is large enough that it
    156 ; encloses the 'maxval' parameter.
    157 ;
    158 ; int Get_Random_Mask(int maxval);
    159 ;
    160 ;*
    161 
    162 	PROC	Get_Random_Mask C near
    163 	USES	ecx
    164 	ARG	maxval:DWORD
    165 
    166 ; This function takes as a parameter a maximum value, for example, 61.  It
    167 ; then tries to create an AND mask that is big enough to enclose that number.
    168 ; For our example case, that AND mask would be 0x3F.  It does this by scanning
    169 ; for the highest bit in the number, then making an all-1's mask from that
    170 ; bit position down to bit 0.
    171 	bsr	ecx,[maxval]		; put bit position of highest bit in ecx
    172 	mov	eax,1			; set one bit on in eax
    173 	jz	??invalid		; if BSR shows maxval==0, return eax=1
    174 	inc	ecx			; get one bit higher than count showed
    175 	shl	eax,cl			; move our EAX bit into position
    176 	dec	eax			; dec it to create the mask.
    177 ??invalid:
    178 	ret
    179 	ENDP	Get_Random_Mask
    180 ;----------------------------------------------------------------------------
    181 
    182 	END
    183 #endif