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