;
; Copyright (c) 1988 Commodore-Amiga, Inc.
;
; Executables based on this information may be used in software
; for Commodore Amiga computers.  All other rights reserved.
;
; This information is provided "as is"; no warranties are made.
; All use is at your own risk, and no liability or responsibility is assumed.
;

		CODE

		NOLIST
		INCLUDE	"exec/types.i"
		INCLUDE "globals.i"
		LIST

		XDEF	RandomSeed,GetRandomSeed,Random

;=============================================================================
; NAME
;    RandomSeed - seed random number generator
;
; SYSNOPSIS
;    RandomSeed( SeedValue1, SeedValue2 )
;		     D0		  D1
;
; FUNCTION
;    Seeds the random number generator
;
; INPUTS
;    SeedValue1 - a longword containing any value you like
;    SeedValue2 - a longword containing any value you like
;
; RESULT
;    Random number generator is initialised
;
; BUGS
;    would be tough to get bugs in this routine !!
;
; SEE ALSO
;
;============================================================================
RandomSeed	movem.l	d0/d1,RND(a5)
		rts

;=============================================================================
; NAME
;    GetRandomSeed - fetch current value in random number generator
;
; SYSNOPSIS
;    RandomSeed = GetRandomSeed()
;	D0/D1
;
; FUNCTION
;    returns current value for later re-seeding to obtain the same sequence
;
; INPUTS
;    none
;
; RESULT
;    RandomSeed - a DOUBLE random seed value
;
; BUGS
;    you gotta be kidding!
;
; SEE ALSO
;
;============================================================================
GetRandomSeed	movem.l	RND(a5),d0/d1
		rts

;=============================================================================
; NAME
;    Random - returns a random integer in the specified range
;
; SYSNOPSIS
;    RndNum = Random( UpperLimit )
;      D0		  D0
;
; FUNCTION
;    returns a random integer in the range 0 to UpperLimit-1
;
; INPUTS
;     UpperLimit - a long(or short will do) in the range 0-65535
;
; RESULT
;    a random integer is returned to you, real quick!
;
; BUGS/LIMITATIONS
;    range was limited to 0-65535 to avoid problems with the DIVU instruction
;    which can return real wierd values if the result is larger than 16 bits.
;
; SEE ALSO
;
;============================================================================
Random		move.w	d0,-(sp)	save range
		beq.s	10$		range of 0 returns 0 always
		bsr.s	LongRnd		get a longword random number
		clr.w	d0		use upper word (it's most random)
		swap	d0
		divu.w	(sp),d0		divide by range...
		clr.w	d0
		swap	d0		...and use remainder for the result
10$		addq.l	#2,sp		scrap range on stack
		rts

; this is the main random number generation routine. Not user callable

LongRnd		movem.l	d2-d3,-(sp)	
		movem.l	RND(a5),d0/d1	D0=LSB's, D1=MSB's of random number
		andi.b	#$0e,d0		ensure upper 59 bits are an...
		ori.b	#$20,d0		...odd binary number
		move.l	d0,d2
		move.l	d1,d3
		add.l	d2,d2		accounts for 1 of 17 left shifts
		addx.l	d3,d3		[D2/D3] = RND*2
		add.l	d2,d0
		addx.l	d3,d1		[D0/D1] = RND*3
		swap	d3		shift [D2/D3] additional 16 times
		swap	d2
		move.w	d2,d3
		clr.w	d2
		add.l	d2,d0		add to [D0/D1]
		addx.l	d3,d1
		movem.l	d0/d1,RND(a5)	save for next time through
		move.l	d1,d0		most random part to D0
		movem.l	(sp)+,d2-d3
		rts

		END
