It is currently Wed Dec 19, 2018 8:16 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 13 posts ] 
Author Message
PostPosted: Mon Feb 23, 2009 2:03 pm 
Offline
User avatar

Joined: Tue Feb 13, 2007 9:02 pm
Posts: 147
Location: Richmond, VA
I'm working on a graphics demo and I want to have a 'random' pattern tile update a 'random' section of my nametable. So, am I correct that the pattern data will choose from one of 256 possibilities and the nametable data will choose from one of 960?

I understand how to update the nametable and redraw the screen, but I don't know how to choose the random values. Will I need a pseudo-random number generator routine or is there a simpler way to do this?

Also, it's only necessary to do a tile at a time.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 23, 2009 2:12 pm 
Offline
User avatar

Joined: Sun Jun 05, 2005 2:04 pm
Posts: 2150
Location: Minneapolis, Minnesota, United States
There is no way to get a truly random value on the NES without writing your own random number generator. This will be pretty difficult because unlike in a computer, there isn't a value that's constantly changing (like a clock or something) to use as a seed. You would probably need to tell the user to press "A" and use the amount of frames (or even CPU cycles if you want REAL precision) as a seed to generate a random number.

EDIT:

noattack wrote:
So, am I correct that the pattern data will choose from one of 256 possibilities and the nametable data will choose from one of 960?


Yes. Though if you want to do attributes, the other 64 bytes of the name table would be used.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 23, 2009 2:26 pm 
Offline
User avatar

Joined: Tue Feb 13, 2007 9:02 pm
Posts: 147
Location: Richmond, VA
How about a continually incrementing counter variable that would be 'polled' at various intervals, whose value would then be used as a tile selection? Although then I suppose the interval would need to be random.

I'm stumped. I'm trying to avoid any user interaction, so using the controller is out for a seed value.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 23, 2009 2:46 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11019
Location: Rio de Janeiro - Brazil
noattack wrote:
Although then I suppose the interval would need to be random.

Exactly. How would you get a random interval without user interaction?

Quote:
I'm trying to avoid any user interaction, so using the controller is out for a seed value.

User input is the only source of randomness I can think of... Other aspects of the NES that might be random (such as register and memory contents) are probably not random enough for seeding a pseudo-random number generator.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 23, 2009 3:08 pm 
Offline
User avatar

Joined: Sun Jun 05, 2005 2:04 pm
Posts: 2150
Location: Minneapolis, Minnesota, United States
Random number generation without user input or an external "seed" is nearly impossible. In a computer, I'm pretty sure they use the time as a seed, because every time it's different. Like Tokumaru said, the only thing that would give you a "random" value would be a register on power up. However, the bad thing about this is usually these registers hold "weird" values; not necessarily random ones. They may hold the same obscure value each time. If in the very beginning of the demo or whatever you're doing, you say "Press A" you can have a loop like this:

loop:
;wait for user to press A, but make sure they're not holding A from the start.
;if didn't press A, increment a variable and loop
;if pressed A, exit loop

And use that incremented value as a seed. This loop would be executed so fast that it would be near humanly impossible to get the same value intentionally. Though I would use a 16-bit variable instead of an 8 bit one, because there are well, more possibilities that way.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 23, 2009 3:22 pm 
Offline
User avatar

Joined: Tue Feb 13, 2007 9:02 pm
Posts: 147
Location: Richmond, VA
So, assuming I don't mind the visual output being the same every time the program is executed, I could set my own seed value and still have it run its course.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 23, 2009 3:25 pm 
Offline
User avatar

Joined: Mon Sep 27, 2004 8:33 am
Posts: 3715
Location: Central Texas, USA
When your program is run, show a title screen and ask the user to press A to start the demo. The following code will generate an 8-bit seed for your pseudo-random number generator:
Code:
; Generates 8-bit random value by waiting for user to press A.
; While waiting for A, it increments X 200000 times per second,
; cycling through all 256 values almost 800 times per second.
; X <- random value
; Preserved: Y
get_rng_seed:
    lda #1
    sta $4016
   
wait_released:
    bit $4016
    bne wait_released
   
    tax
debounce:
    inx
    bne debounce
   
wait_pressed:
    inx
    bit $4016
    beq wait_pressed
       
    rts

By leaving the controller clock line set, it can repeatedly read the status of A in the tight loop. Here's a sample of 100 random values it generated, with me pressing A over and over (you wouldn't have the user press A more than once, but this just shows the quality):

90 17 40 03 1C 47 2B 6A A3 47 37 A2 B8 A0 E8 70 53 12 7F 36 18 F7 D1 38 D0 D4 C8 4D D0 B4 A3 75 0F 6C 55 67 76 C4 C6 D8 E5 96 65 4E 16 E6 33 50 AA EA A2 54 99 62 F4 E1 3B 4E 35 FE 63 4A D1 22 CB 1E C4 F7 12 AC 45 74 B0 29 41 D1 3A 89 53 DC E5 A8 09 22 FD 1C FD 92 4D C4 95 62 4C A3 9D DD 4F F9 21 74


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 23, 2009 3:30 pm 
Offline
User avatar

Joined: Tue Feb 13, 2007 9:02 pm
Posts: 147
Location: Richmond, VA
Awesome. Thank you!


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 23, 2009 5:41 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 11019
Location: Rio de Janeiro - Brazil
noattack wrote:
So, assuming I don't mind the visual output being the same every time the program is executed, I could set my own seed value and still have it run its course.

Yes. If you really don't want any user input, this is your only choice. You can have a pseudo-random number generator and seed it with the same value every time, and you'll get a seemingly random sequence of numbers. They just won't be random at all, because the same sequence will be generated every time the program is run. Some programs even used this to their advantage... If I'm not mistaken, Pitfall for the Atari 2600 used a random number generator to generate the levels, probably because there wasn't space in ROM to store level maps.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 23, 2009 6:25 pm 
Offline
User avatar

Joined: Mon Sep 27, 2004 8:33 am
Posts: 3715
Location: Central Texas, USA
Hmmm, since OAM is dynamic RAM (unlike the rest of VRAM, CHR-RAM, and internal RAM), it seems to get more random values at power. Here's a simple routine to make a hash of the values in OAM at power (be sure to call this before you enable PPU rendering):
Code:
; Generates random value from initial contents of OAM
; A <- Random value
; Preserved: Y
random_from_oam:
    ldx #0
:   stx $2003
    eor $2004
    rol a
    inx
    bne :-
    rts


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 23, 2009 7:54 pm 
Offline

Joined: Sun Sep 19, 2004 11:12 pm
Posts: 20900
Location: NE Indiana, USA (NTSC)
Once you have the seed, you could try something similar to what some of my games do: clock the seed variable as a linear feedback shift register and then read bits off that.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 23, 2009 8:54 pm 
Offline
User avatar

Joined: Tue Feb 13, 2007 9:02 pm
Posts: 147
Location: Richmond, VA
blargg, what is OAM? I can't seem to find an answer in the wiki.


Top
 Profile  
 
 Post subject:
PostPosted: Mon Feb 23, 2009 9:37 pm 
Offline
User avatar

Joined: Sun Jun 05, 2005 2:04 pm
Posts: 2150
Location: Minneapolis, Minnesota, United States
noattack wrote:
blargg, what is OAM? I can't seem to find an answer in the wiki.


OAM is "Object Attribute Memory" (I think that's what it stands for). It holds all the sprite information for each of the 64 sprites: YCoord, Tile, Attribute, XCoord. To my understanding, this is an area inside the NES that you can access with writes/reads to $2003/$2004. I usually don't deal with those because in standard NES game making practice, you reserve a page of RAM with which you do a DMA transfer. That will take all 256 bytes of that page of RAM (I usually use $300-$3FF) and copy it to OAM.


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 13 posts ] 

All times are UTC - 7 hours


Who is online

Users browsing this forum: gauauu and 1 guest


You cannot post new topics in this forum
You cannot reply to topics in this forum
You cannot edit your posts in this forum
You cannot delete your posts in this forum
You cannot post attachments in this forum

Search for:
Jump to:  
Powered by phpBB® Forum Software © phpBB Group