I started looking at the Super Castlevania IV pseudo random number generator to see if it's possible to make the game "more" random or at least a different type of random that's less repeatable. That got me into reading about LFSRs, LCGs, and other PRNGs. I also looked at SMW and MMX2 to see what they do with their PRNG.
SCV4 - Has a 16b LFSR that is left shifted by 1 and then XORed with $2125 if the output bit is 0. It carries the output into another 16b value in memory which is also used in certain functions that need a random sample. This actually is a bad mask for a typical LFSR as gets into the illegal state pretty quickly. But it compensates when this happens by reseeding with the global frame counter. It also seems to step the LFSR a fixed number of times per frame, but then certain enemies (skeletons?) it also steps for AI. So this adds some variability based on how the player works.
MMX2 - 16b PRNG with gets seeded with $D37. LCG-like except the adder isn't constant. The equation is something like the following.
X[15:0] = (3 * X[15:0] & $FF00) + ((((3 * X[15:0]) >>
+ X[7:0]) & 0xFF)
The lower 8b are a sum of the upper 8bits post multiply and the original low order 8bits without a carry. The period is pretty long @ ~43.5k and it never gets in an illegal state. Like SCV4, this will get stepped a variable number of times depending on what's going on in the game.
SMW - Has a 8b LCG and separate 8b LFSR (fibonacci, XNOR). They both are stepped together, XORed to form the upper 8b of the random number, and then the step and XOR is repeated for the lower 8b.
LCG[7:0] = 5 * LCG[7:0] + 1
LFSR[7:0] = ((LFSR[7:0] << 1) | (LFSR XNOR LFSR))
X[15:8] = (LCG_0[7:0] ^ LFSR_0[7:0])
X[7:0] = (LCG_1[7:0] ^ LFSR_1[7:0])
There are two things I'm interested in looking at:
1) Having a different PRNG that provides good random information (in the bits that the game uses) with a sufficient period.
2) Seeding (and possibly reseeding) the PRNG to make the sequence change.
Reading up on PRNG theory got me thinking that how the game uses the bits is probably more important then picking a theoretically "good" PRNG. And the SNES has limited processing time to produce the next number in the sequence which limits what can be used. So maybe something as simple as picking another mask in SCV4 could make a noticeable difference without changing the entire function.
The more interesting thing is probably (2) and how to seed (reseed) with different values to change the game behavior. Using stuff like controller input history, time spent in menus, and maybe even the name entered to the game might be interesting ways to change the game behavior. The game already does some of that as the frame counter starts counting on the name entering screen and doesn't get reset. Any ideas on how to produce unique seeds? Anyone look into PRNGs and/or have some ideas to share?