git.y1.nz

gbdk-2020

GameBoy Development Kit
download: https://git.y1.nz/archives/gbdk.tar.gz
README | Files | Log | Refs | LICENSE

gbdk-lib/libc/asm/sm83/rand.s

      1 ;/***************************************************************************
      2 ; *                                                                         *
      3 ; * Module  : rand.s                                                        *
      4 ; *                                                                         *
      5 ; * Purpose : A rand() generator using the linear congruential method       *
      6 ; *                                                                         *
      7 ; * Version : 1.01, January 7 1998                                          *
      8 ; *             Added _initrand to set seed without recompiling             *
      9 ; *           1, January 6 1998                                             *
     10 ; *                                                                         *
     11 ; * Author  : Luc Van den Borre ( Homepage : NOC.BASE.ORG )                 *
     12 ; *                                                                         *
     13 ; **************************************************************************/
     14 
     15 	;; Why use an algorithm for generating random numbers?
     16 	;;
     17 	;; - Given a certain seed value, the same sequence of random numbers is generated
     18 	;;   every time. This is a good thing when debugging (reproducible). On the other
     19 	;;   hand, you've got 2^16 seed values, each of which will produce a sequence of
     20 	;;   numbers that stays different for any of the other sequences for 'an appreciable
     21 	;;   time.' (I can't say how long exactly.)
     22 	;;
     23 	;; - The linear congruential method is one of the 'best' random number generators
     24 	;;   around. However, this implementation uses a 16 bit accumulator, while at least
     25 	;;   32 bits are needed for a generator that passes all the statistical tests.
     26 	;;   Still, I'm relatively confident that this is random enough for even the most
     27 	;;   demanding game.
     28 	;;
     29 	;;   Compare this to getting random values from one of the hardware registers
     30 	;;   (not reproducible, might not have all values). An array might be the best bet
     31 	;;   if you don't need a lot of values (or have lots of memory spare),
     32 	;;   or if you want values to be within a certain range.
     33 	;;   And both would be faster than this. Also, this definitely isn't the fastest
     34 	;;   algorithm I know, and certainly for games less strict algorithms might be
     35 	;;   appropriate (shift and xor ?).
     36 	;;   It's your choice - but if you're doing Monte Carlo physics simulations on the
     37 	;;   GameBoy, this is a safe bet!
     38 
     39 	.area	_DATA
     40 ___rand_seed::
     41 .randlo:		; Storage for last random number (or seed)
     42 	.ds	0x01
     43 .randhi:
     44 	.ds	0x01
     45 
     46 	.area	_HOME
     47 
     48 	;; Random number generator using the linear congruential method
     49 	;;  X(n+1) = (a*X(n)+c) mod m
     50 	;; with a = 17, m = 65536 and c = $5c93 (arbitrarily)
     51 	;; The seed value is also chosen arbitrarily as $a27e
     52 	;; Ref : D. E. Knuth, "The Art of Computer Programming" , Volume 2
     53 	;;
     54 	;; Exit conditions
     55 	;;   DE = Random number [0,2^16-1]
     56 	;;
     57 	;; Registers used:
     58 	;;   A, HL (need not be saved) and DE (return register)
     59 	;;
     60 
     61 _rand::				; Banked
     62 _randw::			; Banked
     63 	ld hl, #.randlo
     64 	ld a, (hl+)
     65 	ld e, a
     66 	ld d, (hl)		; D = randhi
     67 
     68 	; HL = 17 * DE + 0x5C93
     69 	ld h, d
     70 	ld l, e
     71 
     72 	add hl, hl
     73 	add hl, hl
     74 	add hl, hl
     75 	add hl, hl
     76 	add hl, de
     77 	ld de, #0x5C93
     78 	add hl, de
     79 	
     80 	ld d, l
     81 	ld e, h			; de = return value
     82 
     83 	ld hl, #.randlo
     84 	ld a, d
     85 	ld (hl+), a
     86 	ld (hl), e
     87 	
     88 	;; Note D is the low byte,E the high byte. This is intentional because
     89 	;; the high byte can be slightly 'more random' than the low byte, and I presume
     90 	;; most will cast the return value to a uint8_t. As if someone will use this, tha!
     91 	ret
     92 
     93 	;; This sets the seed value. Call it whenever you like
     94 	;;
     95 	;; Exit conditions
     96 	;;   None
     97 	;;
     98 	;; Registers used:
     99 	;;   A, HL (need not be saved) and DE (return register)
    100 	;;
    101 
    102 _initrand::
    103 	LDA	HL,2(SP)
    104 .initrand::
    105 	LD	A,(HL+)
    106 	LD	(.randlo),A
    107 	LD	A,(HL)
    108 	LD	(.randhi),A
    109 	RET

This webpage is intended to be an accessible preview of this repository. To get a fuller picture, clone it and use the git CLI.