Skip to content

Instantly share code, notes, and snippets.

@raxoft
Created May 22, 2015 07:36
Show Gist options
  • Star 9 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save raxoft/c074743ea3f926db0037 to your computer and use it in GitHub Desktop.
Save raxoft/c074743ea3f926db0037 to your computer and use it in GitHub Desktop.
Fast quality Xor-Shift random number generator for Z80 I have created to weed out the crap RNGs out there. 28 bytes, 122 T cycles, period 2^32-1.
; 8-bit Xor-Shift random number generator.
; Created by Patrik Rak in 2008 and revised in 2011/2012.
; See http://www.worldofspectrum.org/forums/showthread.php?t=23070
org 40000
call rnd ; BASIC driver
ld c,a
ld b,0
ret
rnd ld hl,0xA280 ; yw -> zt
ld de,0xC0DE ; xz -> yw
ld (rnd+4),hl ; x = y, z = w
ld a,l ; w = w ^ ( w << 3 )
add a,a
add a,a
add a,a
xor l
ld l,a
ld a,d ; t = x ^ (x << 1)
add a,a
xor d
ld h,a
rra ; t = t ^ (t >> 1) ^ w
xor h
xor l
ld h,e ; y = z
ld l,a ; w = t
ld (rnd+1),hl
ret
@colawsol
Copy link

colawsol commented Jan 4, 2024

Thank you very much for taking the time to check this! I think I get what you mean about the last store of the C register and I think I now understand this code enough that I've been able to optimise it accordingly by loading out of RAM specifically, rather than using HLI/HLD commands:

rnd:
;	ld  bc,(seed)			; xz -> yw
;	ld  de,(seed+2)			; yw -> zt
;	ld  (seed),de			; x = y, z = w
		ld a,[random+1]
		ld b,a			; b = random+1
		ld a,[random+3]
		ld [random+1],a		; random+3 -> random+1
		ld a,[random]
		ld [random+3],a		; random -> random+3
		ld a,[random+2]
		ld [random],a		; random+2 -> random
		ld e,a			; e = random+2
;	ld  a,e				; w = w ^ ( w << 3 )
        add a,a
        add a,a
        add a,a
        xor e
        ld  e,a
        ld  a,b				; t = x ^ (x << 1)
        add a,a
        xor b
        ld  d,a
        rra				; t = t ^ (t >> 1) ^ w
        xor d
        xor e
;       ld  b,c				; y = z
;       ld  c,a				; w = t
;	ld  (seed+2),bc
		ld [random+2],a
;	ld b,0
	ret

The complication that I didn't mention before is that I am trying to improve the random number generator in a hack of an existing game and calling the function involves bank switching, so the result in the A register is lost by the time the code returns to the point that it called for a random number in the first place anyway. I suppose I could possibly move the function, but I am opting for retrieving the result for now. This does mean spending another byte of code on the retrieval process, but this revision is six bytes less than the original adaption (bringing the total to twenty-four bytes once the random value has been retrieved).

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment