1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
|
.export _randl
.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
;;; 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
|