	;------------------------------------------------------------------
	; Code typed by Peter Thompson on 11 Feb. 92, although written
	; several days earlier. This code is "wareware"; if you use it in
	; any of your programs for which you want money, send me a copy at:
	; 33 Pleasant Street/Pascoe Vale 3044/Australia
	;------------------------------------------------------------------
	; $MUSIC = "The Black Sorrows/Hold On To Me"
	;------------------------------------------------------------------
	; Algorithm adapted from "Algorithms in C", Robert Sedgewick,
	; pub. Addison-Wesley 1990 (he got it from Knuth, vol. 2?)
	;------------------------------------------------------------------

C_GLUE	SET 1
rs_Index		EQU	0
rs_State		EQU	4
RandState_SIZEOF	EQU	4+64*4

	IFD	C_GLUE

;') void rand32init(RandState *d0, ULONG Seed d0)
	PUBLIC	_rand32init
;') ULONG d0 = rnda32(RandState *d0)
	PUBLIC	_rnda32
;') ULONG d0 = rndx32(RandState *d0)
	PUBLIC	_rndx32

	ENDC
	IFND	C_GLUE

	PUBLIC	rand32init
	PUBLIC	rnda32
	PUBLIC	rndx32
	PUBLIC	RandState_SIZEOF

	ENDC

;ULONG d0 = rndm32(ULONG d0)
;alters: d0
	IFD	C_GLUE
_rndm32:
	move.l	4(SP),d0
	ENDC
rndm32:
	movem.l	d1-d3,-(SP)	;d0 d1 d2 d3
	move.l	#31415821,d1	;ab cd -- --
	move.l	d0,d2		;ab cd ab --
	mulu	d1,d0		;BD cd ab --
	move.l	d2,d3		;BD cd ab ab
	swap	d3		;BD cd ab ba
	mulu	d1,d3		;BD cd ab AD
	swap	d1		;BD dc ab AD
	mulu	d1,d2		;BD dc BC AD
	add.l	d2,d3		
	swap	d3
	clr.w	d3
	add.l	d3,d0
	addq.l	#1,d0
	movem.l	(SP)+,d1-d3
	rts

;void rand32init(RandState *d0, ULONG d1 Seed)
;alters: d0,d1,a0,a1
	IFD	C_GLUE
_rand32init:
	move.l	4(SP),d0
	move.l	8(SP),d1
	ENDC
rand32init:
	move.l	d0,a0
	move.l	d0,a1
	move.l	d1,d0
	moveq	#64,d1
riloop:	move.l	d0,(a0)+
	bsr	rndm32
	dbra	d1,riloop
	moveq	#0,d0
	move.l	d0,rs_Index(a1)
	rts

;ULONG d0 = rndx32(RandState *d0)
;alters: d0,d1,a0
	IFD	C_GLUE
_rndx32:
	move.l	4(SP),d0
	ENDC
rndx32:	move.l	d2,-(SP)
	tst.l	d0
	beq.S	rndx32ZZ
	move.l	d0,a0
	move.l	rs_Index(a0),d1		; index = (index+1) mod 64
	addq.b	#4,d1
	move.l	d1,rs_Index(a0)
	moveq	#4*(64-55),d0	; state[index] =
	add.b	d1,d0		;   state[(index+(64-55)) mod 64] xor
	move.l	rs_State(a0,d0.w),d2
	move.b	#4*(64-31),d0	;   state[(index+(64-31)) mod 64];
	add.b	d1,d0
	move.l	rs_State(a0,d0.w),d0
	eor.l	d2,d0
	move.l	d0,rs_State(a0,d1.w)
rndx32ZZ:
	lsr.l	#1,d0
	move.l	(SP)+,d2
	rts

;ULONG d0 = rnda32(RandState *d0)
;alters: d0,d1,a0
	IFD	C_GLUE
_rnda32:
	move.l	4(SP),d0
	ENDC
rnda32:	move.l	d2,-(SP)
	tst.l	d0
	beq.S	rnda32ZZ
	move.l	d0,a0
	move.l	rs_Index(a0),d1		; index = (index+1) mod 64
	addq.b	#4,d1
	move.l	d1,rs_Index(a0)
	moveq	#4*(64-55),d0	; state[index] =
	add.b	d1,d0		;   state[(index+(64-55)) mod 64] +
	move.l	rs_State(a0,d0.w),d2
	move.b	#4*(64-31),d0	;   state[(index+(64-31)) mod 64];
	add.b	d1,d0
	move.l	rs_State(a0,d0.w),d0
	add.l	d2,d0
	move.l	d0,rs_State(a0,d1.w)
rnda32ZZ:
	lsr.l	#1,d0
	move.l	(SP)+,d2
	rts

	END
