Remove support for the original LCG random number generator (#5078)
This commit is contained in:
parent
77148f83a6
commit
17f68563eb
7 changed files with 38 additions and 168 deletions
|
@ -600,12 +600,10 @@ struct LostItem
|
|||
u16 stolen:1;
|
||||
};
|
||||
|
||||
#if HQ_RANDOM == TRUE
|
||||
struct BattleVideo {
|
||||
u32 battleTypeFlags;
|
||||
rng_value_t rngSeed;
|
||||
};
|
||||
#endif
|
||||
|
||||
enum BattleIntroStates
|
||||
{
|
||||
|
@ -707,12 +705,7 @@ struct BattleStruct
|
|||
u16 lastTakenMoveFrom[MAX_BATTLERS_COUNT][MAX_BATTLERS_COUNT]; // a 2-D array [target][attacker]
|
||||
union {
|
||||
struct LinkBattlerHeader linkBattlerHeader;
|
||||
|
||||
#if HQ_RANDOM == FALSE
|
||||
u32 battleVideo[2];
|
||||
#else
|
||||
struct BattleVideo battleVideo;
|
||||
#endif
|
||||
} multiBuffer;
|
||||
u8 wishPerishSongState;
|
||||
u8 wishPerishSongBattlerId;
|
||||
|
|
|
@ -6,25 +6,21 @@
|
|||
#define ISO_RANDOMIZE1(val)(1103515245 * (val) + 24691)
|
||||
#define ISO_RANDOMIZE2(val)(1103515245 * (val) + 12345)
|
||||
|
||||
/* Some functions have been added to support HQ_RANDOM.
|
||||
/* Some functions have been added to support Expansion's RNG implementation.
|
||||
*
|
||||
* If using HQ_RANDOM, you cannot call Random() in interrupt handlers safely.
|
||||
* AdvanceRandom() is provided to handle burning numbers in the VBlank handler
|
||||
* if you choose to do that, and can be used regardless of HQ_RANDOM setting.
|
||||
* LocalRandom(*val) provides a higher-quality replacement for uses of
|
||||
* ISO_RANDOMIZE in vanilla Emerald. You can use LocalRandomSeed(u32) to
|
||||
* create a local state.
|
||||
*
|
||||
* It is no longer possible to call Random() in interrupt handlers safely.
|
||||
* AdvanceRandom() is provided to handle burning numbers in VBlank handlers.
|
||||
* If you need to use random numbers in the VBlank handler, a local state
|
||||
* should be used instead.
|
||||
*
|
||||
* LocalRandom(*val) allows you to have local random states that are the same
|
||||
* type as the global states regardless of HQ_RANDOM setting, which is useful
|
||||
* if you want to be able to set them from or assign them to gRngValue.
|
||||
* LocalRandomSeed(u32) returns a properly seeded rng_value_t.
|
||||
*
|
||||
* Random2_32() was added to HQ_RANDOM because the output of the generator is
|
||||
* always 32 bits and Random()/Random2() are just wrappers in that mode. It is
|
||||
* also available in non-HQ mode for consistency.
|
||||
* Random2_32() was added, even though it is not used directly, because the
|
||||
* underlying RNG always outputs 32 bits.
|
||||
*/
|
||||
|
||||
#if HQ_RANDOM == TRUE
|
||||
struct Sfc32State {
|
||||
u32 a;
|
||||
u32 b;
|
||||
|
@ -70,40 +66,6 @@ static inline u16 Random2(void)
|
|||
}
|
||||
|
||||
void AdvanceRandom(void);
|
||||
#else
|
||||
typedef u32 rng_value_t;
|
||||
|
||||
#define RNG_VALUE_EMPTY 0
|
||||
|
||||
//Returns a 16-bit pseudorandom number
|
||||
u16 Random(void);
|
||||
u16 Random2(void);
|
||||
|
||||
//Sets the initial seed value of the pseudorandom number generator
|
||||
void SeedRng(u16 seed);
|
||||
void SeedRng2(u16 seed);
|
||||
|
||||
//Returns a 32-bit pseudorandom number
|
||||
#define Random32() (Random() | (Random() << 16))
|
||||
#define Random2_32() (Random2() | (Random2() << 16))
|
||||
|
||||
static inline u16 LocalRandom(rng_value_t *val)
|
||||
{
|
||||
*val = ISO_RANDOMIZE1(*val);
|
||||
return *val >> 16;
|
||||
}
|
||||
|
||||
static inline void AdvanceRandom(void)
|
||||
{
|
||||
Random();
|
||||
}
|
||||
|
||||
static inline rng_value_t LocalRandomSeed(u32 seed)
|
||||
{
|
||||
return seed;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
extern rng_value_t gRngValue;
|
||||
extern rng_value_t gRng2Value;
|
||||
|
|
|
@ -1692,15 +1692,9 @@ static void CB2_HandleStartMultiBattle(void)
|
|||
case 8:
|
||||
if (IsLinkTaskFinished())
|
||||
{
|
||||
#if HQ_RANDOM == TRUE
|
||||
struct BattleVideo *ptr = &gBattleStruct->multiBuffer.battleVideo;
|
||||
ptr->battleTypeFlags = gBattleTypeFlags;
|
||||
ptr->rngSeed = gRecordedBattleRngSeed;
|
||||
#else
|
||||
u32 *ptr = gBattleStruct->multiBuffer.battleVideo;
|
||||
ptr[0] = gBattleTypeFlags;
|
||||
ptr[1] = gRecordedBattleRngSeed; // UB: overwrites berry data
|
||||
#endif
|
||||
|
||||
SendBlock(BitmaskAllOtherLinkPlayers(), ptr, sizeof(gBattleStruct->multiBuffer.battleVideo));
|
||||
gBattleCommunication[MULTIUSE_STATE]++;
|
||||
|
|
57
src/main.c
57
src/main.c
|
@ -205,12 +205,9 @@ void SetMainCallback2(MainCallback callback)
|
|||
|
||||
void StartTimer1(void)
|
||||
{
|
||||
if (HQ_RANDOM)
|
||||
{
|
||||
REG_TM2CNT_L = 0;
|
||||
REG_TM2CNT_H = TIMER_ENABLE | TIMER_COUNTUP;
|
||||
}
|
||||
|
||||
REG_TM2CNT_L = 0;
|
||||
REG_TM2CNT_H = TIMER_ENABLE | TIMER_COUNTUP;
|
||||
REG_TM1CNT_H = TIMER_ENABLE;
|
||||
}
|
||||
|
||||
|
@ -218,24 +215,12 @@ void SeedRngAndSetTrainerId(void)
|
|||
{
|
||||
u32 val;
|
||||
|
||||
if (HQ_RANDOM)
|
||||
{
|
||||
REG_TM1CNT_H = 0;
|
||||
REG_TM2CNT_H = 0;
|
||||
val = ((u32)REG_TM2CNT_L) << 16;
|
||||
val |= REG_TM1CNT_L;
|
||||
SeedRng(val);
|
||||
sTrainerId = Random();
|
||||
}
|
||||
else
|
||||
{
|
||||
// Do it exactly like it was originally done, including not stopping
|
||||
// the timer beforehand.
|
||||
val = REG_TM1CNT_L;
|
||||
SeedRng((u16)val);
|
||||
REG_TM1CNT_H = 0;
|
||||
sTrainerId = val;
|
||||
}
|
||||
REG_TM1CNT_H = 0;
|
||||
REG_TM2CNT_H = 0;
|
||||
val = ((u32)REG_TM2CNT_L) << 16;
|
||||
val |= REG_TM1CNT_L;
|
||||
SeedRng(val);
|
||||
sTrainerId = Random();
|
||||
}
|
||||
|
||||
u16 GetGeneratedTrainerIdLower(void)
|
||||
|
@ -254,22 +239,16 @@ void EnableVCountIntrAtLine150(void)
|
|||
#ifdef BUGFIX
|
||||
static void SeedRngWithRtc(void)
|
||||
{
|
||||
#if HQ_RANDOM == FALSE
|
||||
u32 seed = RtcGetMinuteCount();
|
||||
seed = (seed >> 16) ^ (seed & 0xFFFF);
|
||||
SeedRng(seed);
|
||||
#else
|
||||
#define BCD8(x) ((((x) >> 4) & 0xF) * 10 + ((x) & 0xF))
|
||||
u32 seconds;
|
||||
struct SiiRtcInfo rtc;
|
||||
RtcGetInfo(&rtc);
|
||||
seconds =
|
||||
((HOURS_PER_DAY * RtcGetDayCount(&rtc) + BCD8(rtc.hour))
|
||||
* MINUTES_PER_HOUR + BCD8(rtc.minute))
|
||||
* SECONDS_PER_MINUTE + BCD8(rtc.second);
|
||||
SeedRng(seconds);
|
||||
#undef BCD8
|
||||
#endif
|
||||
#define BCD8(x) ((((x) >> 4) & 0xF) * 10 + ((x) & 0xF))
|
||||
u32 seconds;
|
||||
struct SiiRtcInfo rtc;
|
||||
RtcGetInfo(&rtc);
|
||||
seconds =
|
||||
((HOURS_PER_DAY * RtcGetDayCount(&rtc) + BCD8(rtc.hour))
|
||||
* MINUTES_PER_HOUR + BCD8(rtc.minute))
|
||||
* SECONDS_PER_MINUTE + BCD8(rtc.second);
|
||||
SeedRng(seconds);
|
||||
#undef BCD8
|
||||
}
|
||||
#endif
|
||||
|
||||
|
|
34
src/random.c
34
src/random.c
|
@ -8,7 +8,6 @@
|
|||
rng_value_t gRngValue;
|
||||
rng_value_t gRng2Value;
|
||||
|
||||
#if HQ_RANDOM == TRUE
|
||||
|
||||
EWRAM_DATA static volatile bool8 sRngLoopUnlocked;
|
||||
|
||||
|
@ -112,39 +111,6 @@ void AdvanceRandom(void)
|
|||
|
||||
#define LOOP_RANDOM ((u16)(_SFC32_Next(state) >> 16))
|
||||
|
||||
#else
|
||||
EWRAM_DATA static u32 sRandCount = 0;
|
||||
|
||||
u16 Random(void)
|
||||
{
|
||||
gRngValue = ISO_RANDOMIZE1(gRngValue);
|
||||
sRandCount++;
|
||||
return gRngValue >> 16;
|
||||
}
|
||||
|
||||
void SeedRng(u16 seed)
|
||||
{
|
||||
gRngValue = seed;
|
||||
}
|
||||
|
||||
void SeedRng2(u16 seed)
|
||||
{
|
||||
gRng2Value = seed;
|
||||
}
|
||||
|
||||
u16 Random2(void)
|
||||
{
|
||||
gRng2Value = ISO_RANDOMIZE1(gRng2Value);
|
||||
return gRng2Value >> 16;
|
||||
}
|
||||
|
||||
#define LOOP_RANDOM_START
|
||||
#define LOOP_RANDOM_END
|
||||
|
||||
#define LOOP_RANDOM (Random())
|
||||
|
||||
#endif
|
||||
|
||||
#define SHUFFLE_IMPL \
|
||||
u32 tmp; \
|
||||
LOOP_RANDOM_START; \
|
||||
|
|
|
@ -196,13 +196,8 @@ TEST("RandomElement generates a uniform distribution")
|
|||
|
||||
TEST("RandomUniform mul-based faster than mod-based (compile-time)")
|
||||
{
|
||||
#if HQ_RANDOM == TRUE
|
||||
const u32 expectedMulSum = 6;
|
||||
const u32 expectedModSum = 4;
|
||||
#else
|
||||
const u32 expectedMulSum = 3;
|
||||
const u32 expectedModSum = 4;
|
||||
#endif
|
||||
const u32 expectedMulSum = 6;
|
||||
const u32 expectedModSum = 4;
|
||||
struct Benchmark mulBenchmark, modBenchmark;
|
||||
u32 mulSum = 0, modSum = 0;
|
||||
|
||||
|
@ -234,13 +229,8 @@ TEST("RandomUniform mul-based faster than mod-based (compile-time)")
|
|||
|
||||
TEST("RandomUniform mul-based faster than mod-based (run-time)")
|
||||
{
|
||||
#if HQ_RANDOM == TRUE
|
||||
const u32 expectedMulSum = 289;
|
||||
const u32 expectedModSum = 205;
|
||||
#else
|
||||
const u32 expectedMulSum = 232;
|
||||
const u32 expectedModSum = 249;
|
||||
#endif
|
||||
const u32 expectedMulSum = 289;
|
||||
const u32 expectedModSum = 205;
|
||||
u32 i;
|
||||
struct Benchmark mulBenchmark, modBenchmark;
|
||||
u32 mulSum = 0, modSum = 0;
|
||||
|
@ -264,7 +254,6 @@ TEST("RandomUniform mul-based faster than mod-based (run-time)")
|
|||
EXPECT_EQ(modSum, expectedModSum);
|
||||
}
|
||||
|
||||
#if HQ_RANDOM == TRUE
|
||||
TEST("Thumb and C SFC32 implementations produce the same results")
|
||||
{
|
||||
u32 thumbSum;
|
||||
|
@ -286,4 +275,3 @@ TEST("Thumb and C SFC32 implementations produce the same results")
|
|||
|
||||
EXPECT_EQ(thumbSum, cSum);
|
||||
}
|
||||
#endif
|
|
@ -35,20 +35,12 @@
|
|||
#define STATE gBattleTestRunnerState
|
||||
#define DATA gBattleTestRunnerState->data
|
||||
|
||||
#if HQ_RANDOM == TRUE
|
||||
#define RNG_SEED_DEFAULT {0, 0, 0, 0}
|
||||
static inline bool32 RngSeedNotDefault(const rng_value_t *seed)
|
||||
{
|
||||
return (seed->a | seed->b | seed->c | seed->ctr) != 0;
|
||||
|
||||
}
|
||||
#else
|
||||
#define RNG_SEED_DEFAULT 0x00000000
|
||||
static inline bool32 RngSeedNotDefault(const rng_value_t *seed)
|
||||
{
|
||||
return *seed != RNG_SEED_DEFAULT;
|
||||
}
|
||||
#endif
|
||||
#undef Q_4_12
|
||||
#define Q_4_12(n) (s32)((n) * 4096)
|
||||
|
||||
|
@ -1357,17 +1349,13 @@ static void CB2_BattleTest_NextParameter(void)
|
|||
|
||||
static inline rng_value_t MakeRngValue(const u16 seed)
|
||||
{
|
||||
#if HQ_RANDOM == TRUE
|
||||
int i;
|
||||
rng_value_t result = {0, 0, seed, 1};
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
int i;
|
||||
rng_value_t result = {0, 0, seed, 1};
|
||||
for (i = 0; i < 16; i++)
|
||||
{
|
||||
_SFC32_Next(&result);
|
||||
}
|
||||
return result;
|
||||
#else
|
||||
return ISO_RANDOMIZE1(seed);
|
||||
#endif
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
static void CB2_BattleTest_NextTrial(void)
|
||||
|
|
Loading…
Reference in a new issue