.export _randb, _randi, _randl ; .export _rand1in5 ; .export _randbit .importzp sreg, tmp3 .include "atari.inc" ; RANDOM is the POKEY LFSR read address. This appears to be the low 8 ; bits of a 17-bit LFSR (Atari calls it a poly counter). Unfortunately, ; a read from this address will never return 0, since LFSR's can't do ; that. If Atari had made the RANDOM register read the higher order bits ; of the LFSR, rather than the bottom 8, this wouldn't be a problem... but ; they didn't, so there's extra code in here to (try to) compensate. ; 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