Best way to have a number between #$00 and #$XX?

Discuss technical or other issues relating to programming the Nintendo Entertainment System, Famicom, or compatible systems. See the NESdev wiki for more information.

Moderator: Moderators

Post Reply
User avatar
MartsINY
Posts: 66
Joined: Sun Jun 11, 2017 5:39 pm

Best way to have a number between #$00 and #$XX?

Post by MartsINY »

What is the best routine in assembly to have a number from #$00 to a given number?

I have solution but they are complex, I think there is surely an easy with with the instructions?
User avatar
Sogona
Posts: 186
Joined: Thu Jul 23, 2015 7:54 pm
Location: USA
Contact:

Re: Best way to have a number between #$00 and #$XX?

Post by Sogona »

Do you mean like generating a random number between 0 and n?
User avatar
MartsINY
Posts: 66
Joined: Sun Jun 11, 2017 5:39 pm

Re: Best way to have a number between #$00 and #$XX?

Post by MartsINY »

yes exactly what I mean!!

doing

LDA $EF (random generator)
AND #$0F

Some number won't be obtained...
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Best way to have a number between #$00 and #$XX?

Post by tepples »

How are you currently populating the value at address $00EF? What range did you want, and what do you plan to use the numbers for? Does the range vary from call to call? Sometimes this can inform which technique is best.

The general-purpose RNG I recommend nowadays is the LCG from cc65's C library. Sometimes, depending on the exact range I need and how quickly a value should repeat before being reused, I'll post-process the random stream with a least-recently-used generator, calculated over a circular buffer in a manner similar to RC4's mixer.
User avatar
Sogona
Posts: 186
Joined: Thu Jul 23, 2015 7:54 pm
Location: USA
Contact:

Re: Best way to have a number between #$00 and #$XX?

Post by Sogona »

Working with any number that isn't a power of 2 is always tricky.

The way I've been doing it is having a table if values in ROM that's a power of two (The most i've needed is 8 so far, so that's what I've been using), and using a random number as the index for which to choose. Simple and quick.

Code: Select all

lda random
And #%00000111
Tax
Rts
Otherwise you have to use division, which is costly. IDK, I'm sure someone here has a better solution.
User avatar
MartsINY
Posts: 66
Joined: Sun Jun 11, 2017 5:39 pm

Re: Best way to have a number between #$00 and #$XX?

Post by MartsINY »

Sogona: thanks I will use this way!! what is clever and what I was looking for!!
User avatar
MartsINY
Posts: 66
Joined: Sun Jun 11, 2017 5:39 pm

Re: Best way to have a number between #$00 and #$XX?

Post by MartsINY »

tepples wrote:How are you currently populating the value at address $00EF? What range did you want, and what do you plan to use the numbers for? Does the range vary from call to call? Sometimes this can inform which technique is best.

The general-purpose RNG I recommend nowadays is the LCG from cc65's C library. Sometimes, depending on the exact range I need and how quickly a value should repeat before being reused, I'll post-process the random stream with a least-recently-used generator, calculated over a circular buffer in a manner similar to RC4's mixer.

thanks! will look at it!!
User avatar
NovaSquirrel
Posts: 483
Joined: Fri Feb 27, 2009 2:35 pm
Location: Fort Wayne, Indiana
Contact:

Re: Best way to have a number between #$00 and #$XX?

Post by NovaSquirrel »

I usually just keep trying until I get a number out of the randomizer that works. Like this is the code I would use if I wanted 0, 1, 2, 3 or 4 with equal chances:

Code: Select all

loop:
  jsr random  ; get a new random number, put it in the accumulator
  and #7      ; cut down the range
  cmp #5      ; throw out 5, 6 or 7
  bcs loop
tepples
Posts: 22708
Joined: Sun Sep 19, 2004 11:12 pm
Location: NE Indiana, USA (NTSC)
Contact:

Re: Best way to have a number between #$00 and #$XX?

Post by tepples »

Another way to get nearly uniformly distributed numbers from 0 to 4 without the time-uncertainty of looping calls to your RNG is to multiply the RNG's output by 5.

Code: Select all

jsr random

; Multiply A by 5/4 and keep bits 8-6
sta tmp0
lsr a
lsr a
clc
adc tmp0  ; C:A = 0 to 319
and #$C0  ; C:A = 0, 64, 128, 192, or 256
rol a
rol a
rol a
For 5 choices in particular, you can treat values 0-203 one way and 204-255 another, such as returning 4 for all values 204+ and using bits 1-0 of values 0-203.

Code: Select all

jsr random
cmp #204
bcc not4
  lda #4
  bcs haveA
not4:
  and #$03
haveA:
User avatar
Bregalad
Posts: 8056
Joined: Fri Nov 12, 2004 2:49 pm
Location: Divonne-les-bains, France

Re: Best way to have a number between #$00 and #$XX?

Post by Bregalad »

NovaSquirrel wrote:I usually just keep trying until I get a number out of the randomizer that works. Like this is the code I would use if I wanted 0, 1, 2, 3 or 4 with equal chances:

Code: Select all

loop:
  jsr random  ; get a new random number, put it in the accumulator
  and #7      ; cut down the range
  cmp #5      ; throw out 5, 6 or 7
  bcs loop
Just want to point out that's also exactly what I'd do.
User avatar
MartsINY
Posts: 66
Joined: Sun Jun 11, 2017 5:39 pm

Re: Best way to have a number between #$00 and #$XX?

Post by MartsINY »

Bregalad wrote:
NovaSquirrel wrote:I usually just keep trying until I get a number out of the randomizer that works. Like this is the code I would use if I wanted 0, 1, 2, 3 or 4 with equal chances:

Code: Select all

loop:
  jsr random  ; get a new random number, put it in the accumulator
  and #7      ; cut down the range
  cmp #5      ; throw out 5, 6 or 7
  bcs loop
Just want to point out that's also exactly what I'd do.
thx!! it's actually the easiest solution!!
Post Reply