831E Calculate next Random Number Seed value
Submitted by Steve Fewell
Routine:CalcRNDSeed
Name: Calculate the Next Random Number Seed value
Starting Address: &831E
Entry criteria: The Random Number Seed (&0D-&11) contain a 5-byte Random Number Seed value.
Exit: The Random Number Seed (&0D-&11) contain the next Random Number Seed value (based on a specific
calculated sequence).
Description:
This routine calculates the next seed value (in sequence) from the current seed value (in locations &0D-&11).
The calculation is repeated 4 times (once for each byte to be calculated), during each cycle a new byte is calculated and
the other 4 bytes are moved along a position within the Random Number seed value. This enables the calculation to produce
varied (non duplicate) results and to always return a valid 'random' result (i.e. never evaluating to a value of 0, which
would be useless as a seed value). The calculation is designed not to give frequent duplicate values (which would put the
routine into a repitive loop).
This routines sets Y to 4 at the start and repeats the Random Number seed calculation loop (decrementing Y for each loop),
until Y is 0.
-
Each Random Number seed calculation loop obtains a 1-byte result (and moves all other bytes along a position) as follows:
- * Set temp-var1 to the value of location &0F divided by 2 [LSR]
- * Set temp-var2 to the top 4 bits of location &0E plus the bottom 4 bits of temp-var1
- * Copy bottom 2 bits of temp-var2 (bit 0 and bit 1) to the top 2 bits (bit 6 and bit 7) of temp-var3
- * Set bit 5 of temp-var3 to the Carry flag status
- * Set carry flag to bit 2 of temp-var2
- * Copy bit 7, bit 6, bit 5, bit 4 and bit 3 of temp-var2 to bit 4, bit 3, bit 2, bit 1 and bit 0 of temp-var3
- * ROR location &11 (move the bits right, set bit 7 to carry and set carry to the bit lost during the move)
- (where carry is bit 2 of temp-var1 in the previous cycle (or 0 if this is the first cycle))
- * Set temp-var4 to temp-var3 EOR location &11
- * Set location &0D to temp-var4
- * Set location &11 to the byte value at location &10
- * Set location &10 to the byte value at location &0F
- * Set location &0F to the byte value at location &0E
- * Set location &0E to the byte value at location &0D
After the 4 cycles, the location &11 is populated with the value of location &0D value from the previous Random
Number Seed value.
This 5-byte value is used as the mantissa for a Floating-Point value in order to generate a random floating point value
between 0 and 1.
Example 1:
This example shows the calculation of the first &831E call (where the Random Number Seed is currently set to the
initial values: location &0D=>&41; location &0E=>&52; location &0F=>&57;
location &10=>&00 and location &11=>&00.
On entry Carry flag = 0 (?).
On entry: &0D=&41; &0E=&52; &0F=&57; &10=&00; &11=&11.
Y = 4 (number of cycles to process).
[Cycle 1:]
ROR &11 (00000000) => &11 = &00, Carry = 0.
A = &10 => A = &00.
X = A => X = &00.
ROR A => A = &00, carry = 0.
&11 = A => &11 = &00.
A = &0F => A = &57.
&10 = A => &10 = &57.
LSR A (01010111) => A = 00101011 (&2B), carry = 1.
EOR &0E (01010010) => A = 01111001 (&79).
AND #&0F => A = &09.
EOR &0E (01010010) => A = 01011011 (&5B).
ROR A => A = 10101101, carry = 1.
ROR A => A = 11010110, carry = 1.
ROR A => A = 11101011, carry = 0.
ROR A => A = 01110101 (&75), carry = 1.
EOR &11 (00000000) => A = 01110101 (&75).
&11 = X => &11 = &00.
&0F = &0E => &0F = &52.
&0E = &0D => &0E = &41.
&0D = A => &0D = &75.
Now: &0D=&75; &0E=&41; &0F=&52; &10=&57; &11=&00.
Y = Y - 1 => Y = 3.
[Cycle 2:]
ROR &11 (00000000) => &11 = 10000000 (&80) [as Carry was 1], Carry = 0.
A = &10 => A = &57.
X = A => X = &57.
ROR A (01010111) => A = 00101011 (&2B), carry = 1.
&11 = A => &11 = &2B.
A = &0F => A = &52.
&10 = A => &10 = &52.
LSR A (01010010) => A = 00101001 (&29), carry = 0.
EOR &0E (01000001) => A = 01101000 (&68).
AND #&0F => A = &08.
EOR &0E (01000001) => A = 01001001 (&49).
ROR A => A = 00100100, carry = 1.
ROR A => A = 10010010, carry = 0.
ROR A => A = 01001001, carry = 0.
ROR A => A = 00100100 (&24), carry = 1.
EOR &11 (00101011) => A = 00001111 (&0F).
&11 = X => &11 = &57.
&0F = &0E => &0F = &41.
&0E = &0D => &0E = &75.
&0D = A => &0D = &0F.
Now: &0D=&0F; &0E=&75; &0F=&41; &10=&52; &11=&57.
Y = Y - 1 => Y = 2.
[Cycle 3:]
ROR &11 (01010111) => &11 = 10101011 (&AB), Carry = 1.
A = &10 => A = &52.
X = A => X = &52.
ROR A (01010010) => A = 10101001 (&A9), carry = 0.
&11 = A => &11 = &A9.
A = &0F => A = &41.
&10 = A => &10 = &41.
LSR A (01000001) => A = 00100000 (&20), carry = 1.
EOR &0E (01110101) => A = 01010101 (&55).
AND #&0F => A = &05.
EOR &0E (01110101) => A = 01110000 (&70).
ROR A => A = 10111000, carry = 0.
ROR A => A = 01011100, carry = 0.
ROR A => A = 00101110, carry = 0.
ROR A => A = 00010111 (&17), carry = 0.
EOR &11 (10101001) => A = 10111110 (&BE).
&11 = X => &11 = &52.
&0F = &0E => &0F = &75.
&0E = &0D => &0E = &0F.
&0D = A => &0D = &BE.
Now: &0D=&BE; &0E=&0F; &0F=&75; &10=&41; &11=&52.
Y = Y - 1 => Y = 1.
[Cycle 4:]
ROR &11 (01010010) => &11 = 00101001 (&29), Carry = 0.
A = &10 => A = &41.
X = A => X = &41.
ROR A (01000001) => A = 00100000 (&20), carry = 1.
&11 = A => &11 = &20.
A = &0F => A = &75.
&10 = A => &10 = &75.
LSR A (01110101) => A = 00111010 (&3A), carry = 1.
EOR &0E (00001111) => A = 00110101 (&35).
AND #&0F => A = &05.
EOR &0E (00001111) => A = 00001010 (&0A).
ROR A => A = 10000101, carry = 0.
ROR A => A = 01000010, carry = 1.
ROR A => A = 10100001, carry = 0.
ROR A => A = 01010000 (&75), carry = 1.
EOR &11 (00100000) => A = 01110000 (&70).
&11 = X => &11 = &41.
&0F = &0E => &0F = &0F.
&0E = &0D => &0E = &BE.
&0D = A => &0D = &70.
Now: &0D=&70; &0E=&BE; &0F=&0F; &10=&75; &11=&41.
Y = Y - 1 => Y = 0.
The new seed value is: &0D=&70; &0E=&BE; &0F=&0F; &10=&75; &11=&41.
Table showing the initial sequence of Random Number Seed values
(based on the initial startup value and assuming the Seed value is not explicitly reset at any time [using RND(-x)]).
Sequence# |
&0D |
&0E |
&0F |
&10 |
&11 |
|
|
|
|
|
|
Initial values |
&41 |
&52 |
&57 |
&00 |
&00 |
1 (831E called once) |
&70 |
&BE |
&0F |
&75 |
&41 |
2 (831E called twice) |
&2E |
&DB |
&60 |
&41 |
&70 |
3 |
&47 |
&8F |
&02 |
&2D |
&2E |
4 |
&44 |
&34 |
&75 |
&3E |
&47 |
5 |
&E5 |
&D6 |
&7E |
&CC |
&44 |
6 |
&C7 |
&33 |
&51 |
&8B |
&E5 |
7 |
&8A |
&E4 |
&94 |
&D6 |
&C7 |
8 |
&15 |
&D8 |
&02 |
&A5 |
&8A |
9 |
&FA |
&3B |
&00 |
&7F |
&15 |
10 |
&3E |
&B6 |
&3F |
&BC |
&FA |
11 |
&48 |
&31 |
&7C |
&A5 |
&3E |
12 |
&BE |
&91 |
&AA |
&91 |
&48 |
13 |
&C3 |
&A6 |
&CE |
&E1 |
&BE |
14 |
&C9 |
&6A |
&8B |
&9A |
&C3 |
15 |
&DA |
&22 |
&E9 |
&7B |
&C9 |
16 |
&90 |
&33 |
&D9 |
&2F |
&DA |
17 |
&85 |
&91 |
&D5 |
&84 |
&90 |
18 |
&75 |
&99 |
&72 |
&1B |
&85 |
19 |
&F8 |
&16 |
&2E |
&A4 |
&75 |
20 |
&4B |
&88 |
&78 |
&33 |
&F8 |
|
|
|
|
|
|
After setting seed value to -1 [RND(-1)] |
&FF |
&FF |
&FF |
&FF |
&40 |
#1 |
&FF |
&07 |
&00 |
&80 |
&FF |
#2 |
&F8 |
&FF |
&7F |
&C0 |
&FF |
|
|
|
|
|
|
After setting seed value to -&FFFFFFFF |
&E0 |
&7D |
&BD |
&DE |
&17 |
#1 |
&78 |
&BD |
&80 |
&38 |
&E0 |
#2 |
&C5 |
&DF |
&97 |
&17 |
&78 |
Disassembly for the Calculate next Random Number Seed value routine
831E |
|
160 004 |
A0 04 |
LDY#&04 |
8320 |
f |
102 017 |
66 11 |
ROR &11 |
8322 |
|
165 016 |
A5 10 |
LDA &10 |
8324 |
|
170 |
AA |
TAX |
8325 |
j |
106 |
6A |
ROR A |
8326 |
|
133 017 |
85 11 |
STA &11 |
8328 |
|
165 015 |
A5 0F |
LDA &0F |
832A |
|
133 016 |
85 10 |
STA &10 |
832C |
J |
074 |
4A |
LSR A |
832D |
E |
069 014 |
45 0E |
EOR &0E |
832F |
) |
041 015 |
29 0F |
AND#&0F |
8331 |
E |
069 014 |
45 0E |
EOR &0E |
8333 |
j |
106 |
6A |
ROR A |
8334 |
j |
106 |
6A |
ROR A |
8335 |
j |
106 |
6A |
ROR A |
8336 |
j |
106 |
6A |
ROR A |
8337 |
E |
069 017 |
45 11 |
EOR &11 |
8339 |
|
134 017 |
86 11 |
STX &11 |
833B |
|
166 014 |
A6 0E |
LDX &0E |
833D |
|
134 015 |
86 0F |
STX &0F |
833F |
|
166 013 |
A6 0D |
LDX &0D |
8341 |
|
134 014 |
86 0E |
STX &0E |
8343 |
|
133 013 |
85 0D |
STA &0D |
8345 |
|
136 |
88 |
DEY |
8346 |
|
208 216 |
D0 D8 |
BNE -40 --> &8320 |
8348 |
` |
096 |
60 |
RTS |
Or