/* This file is part of jpcsp. Jpcsp is free software: you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any later version. Jpcsp is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with Jpcsp. If not, see <http://www.gnu.org/licenses/>. */ package jpcsp.HLE.modules; import org.apache.log4j.Logger; import jpcsp.Memory; import jpcsp.HLE.HLEFunction; import jpcsp.HLE.HLEModule; import jpcsp.HLE.Modules; import jpcsp.HLE.TPointer; import jpcsp.HLE.kernel.types.SceMT19937; public class sceMt19937 extends HLEModule { public static Logger log = Modules.getLogger("sceMt19937"); // Based on http://beam.acclab.helsinki.fi/~knordlun/mc/mt19937.c /* A C-program for MT19937: Real number version */ /* genrand() generates one pseudorandom real number (double) */ /* which is uniformly distributed on [0,1]-interval, for each */ /* call. sgenrand(seed) set initial values to the working area */ /* of 624 words. Before genrand(), sgenrand(seed) must be */ /* called once. (seed is any 32-bit integer except for 0). */ /* Integer generator is obtained by modifying two lines. */ /* Coded by Takuji Nishimura, considering the suggestions by */ /* Topher Cooper and Marc Rieffel in July-Aug. 1997. */ /* This library is free software; you can redistribute it and/or */ /* modify it under the terms of the GNU Library General Public */ /* License as published by the Free Software Foundation; either */ /* version 2 of the License, or (at your option) any later */ /* version. */ /* This library is distributed in the hope that it will be useful, */ /* but WITHOUT ANY WARRANTY; without even the implied warranty of */ /* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. */ /* See the GNU Library General Public License for more details. */ /* You should have received a copy of the GNU Library General */ /* Public License along with this library; if not, write to the */ /* Free Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA */ /* 02111-1307 USA */ /* Copyright (C) 1997 Makoto Matsumoto and Takuji Nishimura. */ /* Any feedback is very welcome. For any question, comments, */ /* see http://www.math.keio.ac.jp/matumoto/emt.html or email */ /* matumoto@math.keio.ac.jp */ public static class MT19937 { public static final int N = 624; private static final int M = 397; private static final int MATRIX_A = 0x9908b0df; /* constant vector a */ private static final int UPPER_MASK = 0x80000000; private static final int LOWER_MASK = 0x7FFFFFFF; private static final int[] mag01 = new int[] { 0, MATRIX_A }; /* Tempering parameters */ public static final int TEMPERING_MASK_B = 0x9d2c5680; public static final int TEMPERING_MASK_C = 0xefc60000; public static final int TEMPERING_SHIFT_U = 11; public static final int TEMPERING_SHIFT_S = 7; public static final int TEMPERING_SHIFT_T = 15; public static final int TEMPERING_SHIFT_L = 18; protected static void init(SceMT19937 mt19937, int seed) { mt19937.mt[0] = seed; for (int mti = 1; mti < N; mti++) { mt19937.mt[mti] = 69069 * mt19937.mt[mti - 1]; } mt19937.mti = N; } protected static int getInt(SceMT19937 mt19937) { if (mt19937.mti >= N) { // Generate N words at one time if (mt19937.mti == N + 1) { // init has not been called init(mt19937, 4357); } int kk; for (kk = 0; kk < N-M; kk++) { int y = (mt19937.mt[kk] & UPPER_MASK) | (mt19937.mt[kk + 1] & LOWER_MASK); mt19937.mt[kk] = mt19937.mt[kk + M] ^ (y >>> 1) ^ mag01[y & 0x1]; } for (; kk < N - 1; kk++) { int y = (mt19937.mt[kk] & UPPER_MASK) | (mt19937.mt[kk + 1] & LOWER_MASK); mt19937.mt[kk] = mt19937.mt[kk + (M - N)] ^ (y >>> 1) ^ mag01[y & 0x1]; } int y = (mt19937.mt[N - 1] & UPPER_MASK) | (mt19937.mt[0] & LOWER_MASK); mt19937.mt[N - 1] = mt19937.mt[M - 1] ^ (y >>> 1) ^ mag01[y & 0x1]; mt19937.mti = 0; } long y = mt19937.mt[mt19937.mti++]; y ^= y >> TEMPERING_SHIFT_U; y ^= (y << TEMPERING_SHIFT_S) & TEMPERING_MASK_B; y ^= (y << TEMPERING_SHIFT_T) & TEMPERING_MASK_C; y ^= (y >> TEMPERING_SHIFT_L); return (int) y; } } @HLEFunction(nid = 0xECF5D379, version = 150) public int sceMt19937Init(TPointer mt19937Addr, int seed) { SceMT19937 mt19937 = new SceMT19937(); MT19937.init(mt19937, seed); mt19937.write(mt19937Addr); return 0; } @HLEFunction(nid = 0xF40C98E6, version = 150) public int sceMt19937UInt(SceMT19937 mt19937) { int random = MT19937.getInt(mt19937); if (log.isDebugEnabled()) { log.debug(String.format("sceMt19937UInt returning 0x%08X", random)); } mt19937.write(Memory.getInstance()); return random; } }