Getting random number from 6502 assembler
The SID chip can actually generate numbers that are more random than BASIC's pseudo-random numbers. Start the generator with:
LDA #$FF ; maximum frequency value
STA $D40E ; voice 3 frequency low byte
STA $D40F ; voice 3 frequency high byte
LDA #$80 ; noise waveform, gate bit off
STA $D412 ; voice 3 control register
RTS
Then you can get random numbers whenever you want with:
LDA $D41B ; get random value from 0-255
Thanks to Ross Ridge for suggesting that the called function was changing the value in the Y register. I knew it had to be something obvious!
By storing Y before the JSR
, and restoring after, it now will iterate properly. Here is the quick fix:
Edit: Updated 7/10/17 - to show full code and incorporate JeremyP suggestion. This is essentially a coin flip iterator (50000 repetitions) for purposes of experimenting with random
.C 033c A9 00 LDA #$00
.C 033e 85 FB STA $FB ; set up register for counter
.C 0340 85 FC STA $FC
.C 0342 A2 C8 LDX #$C8 ; outer loop= 200
.C 0344 86 FD STX $FD
.C 0346 A0 FA LDY #$FA ; inner loop=250
.C 0348 84 FE STY $FE
.C 034a 20 94 E0 JSR $E094 ; Get random# Vic20 Address (E09B for C64)
.C 034d A5 63 LDA $64
.C 034f C9 80 CMP #$80 ; >128 = HEADS
.C 0351 90 0D BCC $0360 ; else continue loop
.C 0353 18 CLC ; increment 2 byte number
.C 0354 A5 FB LDA $FB
.C 0356 69 01 ADC #$01 ; LSB
.C 0358 85 FB STA $FB
.C 035a A5 FC LDA $FC
.C 035c 69 00 ADC #$00 ; MSB
.C 035e 85 FC STA $FC
.C 0360 C6 FE DEC $FE
.C 0362 D0 E6 BNE $034A ; end inner loop
.C 0364 C6 FD DEC $FD
.C 0366 D0 DE BNE $0346 ; end outer loop
.C 0368 60 RTS ; return to basic
I can get the random number by LDA $63
or LDA $64
inside the loop and use it for my purposes.
This turned out to be a lot slower than expected, taking only half the time it would've taken in BASIC. The RND function takes a lot of cycles, however, I found this Compute! article which uses the SID chip as a random number generator.
LDA #$FF ; maximum frequency value
STA $D40E ; voice 3 frequency low byte
STA $D40F ; voice 3 frequency high byte
LDA #$80 ; noise waveform, gate bit off
STA $D412 ; voice 3 control register
Once turned on it generates numbers independently and doesn't have to be executed again. A loop that repeatadly calls LDA $D41B
will get you a new random number on each iteration. In my test 50,000 iterations took 1.25 seconds and million took a little over 24 seconds. Pretty impressive for a 1MHz computer!