Interesting, it works also on Z80SIM! (very good work, Udo!).Some software we were using in the 80s used R, so I implemented it to get correct results.
At last, it seems I have the perfect random numbers generator for Z80.
George Marsaglia's xorshift
I wonder how many Z80 simulators/emulators will correctly execute
the 'ld a,r' instruction ?
At last, it seems I have the perfect random numbers generator for Z80.
A couple of years ago, I discovered John Metcalf's 16 bits random numbers generator (based on George Marsaglia's xorshift), it is small and fast:
; generates 16-bit pseudorandom numbers with a period of 65535
; using the xorshift method:
; hl ^= hl << 7
; hl ^= hl >> 9
; hl ^= hl << 8
_xrnd:
ld hl,1 ; seed must not be 0
ld a,h
rra
ld a,l
rra
xor h
ld h,a
ld a,l
rra
ld a,h
rra
xor l
ld l,a
xor h
ld h,a
ld (_xrnd+1),hl
ret
, but I needed also a good-enough 'set-seed-value' routine (to set the initial value at _xrnd+1).
Until now, I loaded the seed value from 0C000H (for a RC2014) or added the screen characters (for Z80ALL). Not good enough, true?
The last weekend I read (I do not remember exactly where...) a hint about using the Z80 R register, for this purpose.
So, here it is, the set-seed-value routine:
_xrndseed:
ld a,r
ld l,a
ld a,r
ld h,a
or l ; HL must be not NULL
jr nz,1f
inc hl
1:
ld (_xrnd+1),hl
ret
I used these routines for my last game (TextFall), and they work perfectly.
I mean, each game starts with a new visual configuration, different form the last one ( it will be boring to play-it allways starting from the same setup, no ? )
Interesting, it works also on Z80SIM! (very good work, Udo!).
In fact, I'm away on vacation, and I only have my laptop with me (not also a RC2014...) ; however, I managed these days to write TextFall, which uses the new random numbers generator, only using Z80SIM.
I wonder how many Z80 simulators/emulators will correctly execute the 'ld a,r' instruction ? It's all about how the simulator implements the R register...
Can anyone test-it on other Z80 simulators?
Ladislau
PS. Once returned from vacation, I will update all the games I published lately, to benefit from the new random numbers generator...
... And it even gives you a way of checking whether interrupts were
previously enabled or not in e.g. an NMI handler.
-Rus.
Russell Marks wrote:[...]
... And it even gives you a way of checking whether interrupts were
previously enabled or not in e.g. an NMI handler.
The Z80 CPU already does this for NMI, as long as you use RETN to
return from the NMI handler.
Ah, but what if you don't return because the hardware uses the NMI to implement a soft power-off button? I actually used this one in ZCN (in src/powrhndl.z), which is why I mentioned it. :-)
-Rus.
Russell Marks wrote:[...]
Ah, but what if you don't return because the hardware uses the NMI to
implement a soft power-off button? I actually used this one in ZCN (in
src/powrhndl.z), which is why I mentioned it. :-)
If you're powering off, do you care if interrupts were enabled or
not?
TESTRAND N
TESTRAND 11002202001101111202111111112000001102222202121211221200101100220 0001200222221012100021121112110200211212011211011122120112112020
TESTRAND 21222222222222222222222222222222222222222222222222222222222222222 2222222222222222222222222222222222222222222222222222222222222222 2222222222222222222222222222222222222222222222222222222222222222
TESTRAND 42444444444444444444444444444444444444444444444444444444444444444 4444444444444444444444444444444444444444444444444444444444444444
TESTRAND 84888888888888888888888888888888888888888888888888888888888888888 8888888888888888888888888888888888888888888888888888888888888888
Those results look suspiciously "perfect" (aside from the anomaly for value "0"). If I run a similar test on Java in Linux (which might be using the Linux rand number generator, but either way should be a very good one), I do not get "perfect"distribution. I suspect your xrnd routine is "running out of steam" and failing to produce randomness after a while (might be degenerating into just plain counting).
The program I'm using is:
-----------------------------------------------
import java.util.Random;
public class rand {
Random random;
byte[] Hits;
public rand(int N) {
random = new Random();
Hits = new byte[32768];
for (int x = 0; x < N; ++x) {
for (int y = 0; y < Hits.length; ++y) {
int r = random.nextInt() & 0x7fff;
++Hits[r];
}
}
for (int y = 0; y < Hits.length; ++y) {
System.out.format("%c", Hits[y] < 10 ? '0' + Hits[y] : 'v');
}
System.out.format("\n");
}
public static void main(String[] args) {
if (args.length != 1) {
System.err.format("Usage: rand N\n");
System.exit(1);
}
int N = Integer.valueOf(args[0]);
new rand(N);
}
}
------------------------------------------------
And I get output for "4" that is:
========================= 3351634325624331v75415332342238737447335455318451633342647445631 4423334933342434875548514462423321263353335322556521453624323433
...
36115454617525457137144696443414252112321663v17336v3343722246112 43845205472v2553124866443223241734214236412344653433414645235353 =========================
(the 'v' characters indicate a count greater than 9)
BDS-C had a pretty good pseudo-random number generator, although it uses a 32-bit seed. Code is pretty simple:
-----------------------------------
FUNCTION rand
lhld rseed
xchg
mvi a,48h
ana e
jz rand1
jpe rand1
stc
rand1: lhld rseed+2
mov a,h
ral
mov h,a
mov a,l
ral
mov l,a
shld rseed+2
mov a,d
ral
mov h,a
mov a,e
ral
mov l,a
shld rseed
mov a,h
ani 7fh
mov h,a
ret
ENDFUNC
-----------------------------------------
This returns a 15-bit pseudo-random number. The distribution test shows a pattern much more like modern random number generators. It does require, or at least should have, a 32-bit seed.
TESTRAND 11020101220114220102203121331212010001132111300211120421220021213 1010010010010110110130210010020203100000011310310302000111203012
TESTRAND 27423433323222134003004031301302220324010132510142320017321422352 6204431313113112311341241312414533021422212316272121211215322745
TESTRAND 44435626428555933229446728168192441475652285523442443555452383238 3311436332533536532517153454234536527244943773415516357161577555
TESTRAND 874667988779@988856:596=5;6788:67:88786;9:<9:4=7679:469696778>549 6:4<;797>;985<1<7;6:<4896469;467<88>76765765666;484;5<6=;:7546@8
Intending to test the the quality of the XorShift algorithm, I wrote[...]
the following TESTRAND program
I hope this test shows without a doubt the quality of the XorShift algorithm...
Sysop: | Keyop |
---|---|
Location: | Huddersfield, West Yorkshire, UK |
Users: | 491 |
Nodes: | 16 (2 / 14) |
Uptime: | 92:25:30 |
Calls: | 9,679 |
Files: | 13,723 |
Messages: | 6,174,011 |