*  You must seed the random function first. It would be best to seed it
*  with the current time, as returned by intuition CurrentTime.
*
*  To generate the number place the limit in d0 and call Random. You are
*  returned a value in the range from 0 to limit-1.
*

;=========================
; RandomSeed(seed)
;             d0
;=========================
RandomSeed:
        ADD.L   D0,D1        ;   user seed in d0 (d1 too)
        MOVEM.L D0/D1,RND
; drops through to the main random function (not user callable)
LongRnd:
        MOVEM.L D2-D3,-(SP)
        MOVEM.L RND,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    ;   save for next time through
        MOVE.L  D1,D0        ;   most random part to D0
        MOVEM.L (SP)+,D2-D3
        RTS

;=========================
;Random(limit)
;         d0
;=========================
Random: MOVE.W  D2,-(SP)
        MOVE.W  D0,D2        ;   save upper limit
        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  D2,D0        ;   divide by range...
        CLR.W   D0           ;   ...and use remainder for the value
        SWAP    D0           ;   result in D0.W
10$     MOVE.W  (SP)+,D2
        RTS

RND     DS.L    2            ;   random number
