RAND16 EQU >83C0 . . . LI R4,28645 MPY @RAND16,R4 AI R5,31417 MOV R5,@RAND16The address >830C is used because the console "OS" (if you can call it that) places the amount of time it took the user to press a key on the Mater Title Screen (or something like that anyway.) So, it makes for a truly random seed value. After that it falls down miserably.
Good random numbers usually start with prime numbers, since random numbers in computers are fake anyway (which is why we call them pseudo-random numbers), using primes help make them as random as possible (so I have read.) When I first used this code I had no idea what those numbers were for and why they were chosen, I was just happy to have some random looking numbers. In the last few projects I've done, when I was reviewing the code, I assumed they were at least prime, but I just checked and they are not!
Also, the code above has the non random feature of producing an odd number, then even, then odd, then even, etc. Not very random. Adamantyr posted a variation that he uses in his code that mixes up the bits depending on the current "tick" (a counter that is incremented every VSYNC), and this helps scramble things up and at the very least gets rid of the odd, even, odd nature of the original. Here is his code (taken from a previous post):
LI R4,23729 MPY @>83C0,R4 AI R5,31871 MOV @CLOCK,R0 ANDI R0,>000F SRC R5,0 MOV R5,@>83C0The top part is the same, but after the addition he uses the bottom 4-bits of the tick counter to be a 0 to 15 bit circular shift of the random number. When you use a zero count with the shift instructions, the count is taken from R0. His numbers are a little different than the original ones from Tombstone City, but they are also not prime:
28645 is not prime. It is divisible by 5.
31417 is not prime. It is divisible by 89.
23729 is not prime. It is divisible by 61.
31871 is not prime. It is divisible by 7.
So, I've made a few modifications in an attempt to make this thing a little more random. Keep in mind that a RNG is deep math and science and I in no way pretend to have a solid grasp on any of this. I just know that the original RNG creates very *bad* random numbers, and this one produces numbers that look and act much more random.
RAND16 EQU >83C0 . . . ********************************************************************* * * Generates a weak pseudo random number and places it in RAND16 * * R4 - Destroyed * R5 - 16-bit random number and stored in RAND16 for next round * RANDNO LI R4,28643 * A prime number to multiply by MPY @RAND16,R4 * Multiply by last random number AI R5,31873 * Add a prime number MOV R0,R4 * Save R0 MOV @TICK,R0 * Use the VSYNC tick to mix it up a little ANDI R0,>000F * Check if shift count is 0 JEQ RAND01 * A 0 count means shift 16, which is a wash SRC R5,0 * Mix up the number to break odd/even pattern RAND01 MOV R5,@RAND16 * Save this number for next time MOV R4,R0 * Restore R0 B *R11 *// RANDNOThis is a slight variation on Adamantyr's code in that I'm checking if the number of bits to rotate is zero, since a zero count in R0 means shift 16 bits, which since the shift being used is circular (SRC), does nothing except take the max clock cycles for a shift instruction which is about 56 clocks. I also save and restore R0 (R0 has to be used because it is the only register that can hold a variable-based count for the shift instructions.)
This will be going into my assembly language tutorial, which is the main reason I was revisiting it. The demo I set up was not filling the screen randomly, there were definite patterns that make it easy to see how *not random* the original was.
Edited by matthew180, Wed May 26, 2010 12:04 PM.