.export _randl, _rand1to3 .import _rand ; .export _randb, _randi, _randl ; .export _rand1in5 ; .export _randbit .importzp sreg, tmp3 .include "atari.inc" .ifdef CART_TARGET .segment "HIGHCODE" .else .code .endif ; unsigned long __fastcall__ randl(void); ; this returns the full range of an unsigned long, 0 to 2**32-1 _randl: jsr _rand sta sreg jsr _rand sta sreg+1 jsr _rand sta tmp3 jsr _rand ldx tmp3 rts ; return 1, 2, or 3. equivalent to: randi()%3+1 ; replacing both occurences of the expression in taipan.c with a calls ; to this function saves 11 bytes. _rand1to3: jsr _rand ; returns 16 bits: X is MSB (which we ignore), A is LSB and #$03 ; A now 0..3 beq _rand1to3 ; try again, if it's 0 ldx #0 ; now A is 1..3, but we have to force X to 0... rts ;;; rest of file is commented out ; RANDOM is the POKEY LFSR read address. According to the POKEY data ; sheet, this is the high 8 bits bits of a 17-bit LFSR (Atari calls it ; a poly counter). Unfortunately, a read from this address never seems ; to return 0, which confuses me: an LFSR can never return 0, but since ; we're only reading 8 bits of it, we should be able to get a 0 (some ; of the other 9 bits would still be 1). ; After some crude statistical analysis, I've decided to go with cc65's ; rand() implementation. It seems to return more evenly distributed ; results. ; Might use this at some point: ;_randbit: ; lda RANDOM ; asl ; lda #0 ; adc #0 ; rts ; unsigned char __fastcall__ randbit(void); ;_randbit: ; ldx #0 ;randbit: ; lda RANDOM ; lsr ; and #$01 ; rts ; This doesn't give evenly distributed results, it's twice as ; likely to return 2 or 3 than 0, 1, or 4. ; unsigned char __fastcall__ rand1in5(void); ;_rand1in5: ; ldx #0 ;rand1in5: ; lda RANDOM ; lsr ; lsr ; and #$03 ; adc #0 ; rts ; unsigned char __fastcall__ randb(void); ;;_randb: ; C-callable entry point ;; ldx #0 ;;randb: ; asm-callable (doesn't trash X reg) ;; lda RANDOM ; bit 7 of this read ends up as bit 0 of result ;; sta tmp3 ;; nop ; let the LFSR cook for a bit... ;; nop ;; lda RTCLOK+2 ; different amount of cooking depending on whether ;; and #$01 ; we're on an even or odd numbered TV frame ;; bne @1 ;; nop ;; nop ;; nop ;;@1: ;; rol tmp3 ; tmp3 bit 7 now in carry ;; lda RANDOM ;; rol ; carry now in bit 0 of A ;; nop ;; nop ;; rts ; unsigned int __fastcall__ randi(void); ; NB cc65's rand() returns a positive signed int, meaning ; 0 to 0x7fff. ;;_randi: ;; jsr randb ;; and #$7f ;; tax ;; jsr randb ;; rts ; unsigned long __fastcall__ randl(void); ; this returns the full range of an unsigned long, 0 to 2**32-1 ;;_randl: ;; jsr randb ;; sta sreg ;; jsr randb ;; sta sreg+1 ;; jsr randb ;; tax ;; jsr randb ;; rts