wallaby Posted September 6, 2016 Share Posted September 6, 2016 OKay, I've read you can seed rand by setting it to a value. Like rand = 30. That will then give you a repeatable pattern of random numbers. This is a powerful feature of random number generators. But, there is an interesting problem with the Atari 2600. Can you only seed the rand function with a byte? So there can only be 256 sequences? Most of the time, a seed with be the number of seconds since 1970 or whatever, so the seed is always different. But you have the option of setting the seed to potentially millions of possible sequences. Is there a way to set the DPC+ seed to a larger number? Quote Link to comment Share on other sites More sharing options...
+hloberg Posted September 6, 2016 Share Posted September 6, 2016 there is no way that the 2600 can know the seconds since 1970 so what does make the seed? Quote Link to comment Share on other sites More sharing options...
RevEng Posted September 6, 2016 Share Posted September 6, 2016 DPC+ uses a hardware random number generator in the ARM chip. [edit - gladly corrected by Darrell below!] Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted September 6, 2016 Share Posted September 6, 2016 DPC+ uses a 32 bit number, not 8 bit. It's implemented as an LFSR in software. The implementation in Stella, which corresponds to the ARM assembly code used in the DPC+ driver, is: // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void CartridgeDPCPlus::clockRandomNumberGenerator() { // Update random number generator (32-bit LFSR) myRandomNumber = ((myRandomNumber & (1<<10)) ? 0x10adab1e: 0x00) ^ ((myRandomNumber >> 11) | (myRandomNumber << 21)); } Additionally, the LFSR used is reversible (not all are). // - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - inline void CartridgeDPCPlus::priorClockRandomNumberGenerator() { // Update random number generator (32-bit LFSR, reversed) myRandomNumber = ((myRandomNumber & (1u<<31)) ? ((0x10adab1e^myRandomNumber) << 11) | ((0x10adab1e^myRandomNumber) >> 21) : (myRandomNumber << 11) | (myRandomNumber >> 21)); } A reversable LFSR is useful for things like creating the world in Pitfall where if you exit a screen to the left, then exit that screen to the right, you should end up where you started. You can use demo 3 to see the sequence of random numbers. There are 5 registers for reading the random number: ;---------------------------------------- ; Random Numbers ;---------------------------------------- ; DPC+ provides a 32 bit LFSR (Linear feedback shift register) ; which is used as a random number generator. Each individual byte of the ; random number will return values from 0-255. The random numbers will follow ; an exact sequence, so it's best to clock them at least once per frame even if ; you don't need the value (this allows the amount of time it takes the user to ; start the game to select a random starting point in the sequence) ;---------------------------------------- RANDOM0NEXT DS 1 ; $00 clock next 32 bit number and returns byte 0 RANDOM0PRIOR DS 1 ; $01 clock prior 32 bit number and returns byte 0 RANDOM1 DS 1 ; $02 returns byte 1 of random number w/out clock RANDOM2 DS 1 ; $03 returns byte 2 of random number w/out clock RANDOM3 DS 1 ; $04 returns byte 3 of random number w/out clock The two RANDOM0 registers will advance the value to either the next, or the prior, and return byte 0 of the 32 bit (4 byte) random number. After that you can use RANDOM1, RANDOM2 and RANDOM3 to get the other 3 bytes. Been a while since I've looked at bB, but I think you could use the values like this: a = RANDOM0NEXT if (a & 1) then DO_SOMETHING a = RANDOM1 if (a < 128) then DO_SOMETHING_ELSE ... a = RANDOM3 if (a >= 64) then DO_YET_SOMETHING_ELSE and maybe even this: if (RANDOM0NEXT & 1) then DO_SOMETHING if (RANDOM1 < 128) then DO_SOMETHING_ELSE ... if (RANDOM3 >= 64) then DO_YET_SOMETHING_ELSE One thing to remember is if you do this: a = RANDOM0NEXT b = RANDOM0NEXT c = RANDOM0NEXT then a, b, and c will most likely have different values because you told DPC+ to advance the LFSR. However, if you do this: a = RANDOM1 b = RANDOM1 c = RANDOM1 then a, b, and c are guaranteed to have the same value because you did not tell DPC+ to advance the LFSR. There are also 5 registers for seeding the random number: ;---------------------------------------- ; Random Number Initialization ;---------------------------------------- ; The random number generate defaults to a value that spells out DPC+. ; Store any value to RRESET to set the random number back to DPC+, or you ; can use RWRITE0-3 to change the 32 bit value to anything you desire. ; ; reset random number ; LDA #0 ; STA RRESET ; ; set a specific random number (spells out 2600) ; LDA #$32 ; STA RWRITE0 ; LDA #$36 ; STA RWRITE1 ; LDA #$30 ; STA RWRITE2 ; STA RWRITE3 ; ; NOTE: do not set all 4 bytes to 0, as that will disable the generator. ;---------------------------------------- RRESET DS 1 ; $70 RWRITE0 DS 1 ; $71 RWRITE1 DS 1 ; $72 RWRITE2 DS 1 ; $73 RWRITE3 DS 1 ; $74 RRESET will put the value back to the powerup value, assign it any value to trigger the reset: RRESET = 1 RWRITE0 thru RWRITE3 let you assign any value you want, just don't make them all 0s or that will disable the LFSR. As an example: RWRITE0 = 11 RWRITE1 = 9 RWRITE2 = 19 RWRITE3 = 66 1 Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted September 6, 2016 Share Posted September 6, 2016 there is no way that the 2600 can know the seconds since 1970 so what does make the seed? The default seed is: void CartridgeDPCPlus::setInitialState() { ... // Initialize the DPC's random number generator register (must be non-zero) myRandomNumber = 0x2B435044; // "DPC+" } The ASCII values are: 0x44 = D 0x50 = P 0x43 = C 0x2B = + The order is the opposite of you might expect, that's because the ARM (like the 6507) is little-endian. That value shows up twice in the DPC+ and is part of what Stella uses to auto-detect a DPC+ ROM: bool Cartridge::isProbablyDPCplus(const uInt8* image, uInt32 size) { // DPC+ ARM code has 2 occurrences of the string DPC+ uInt8 signature[] = { 'D', 'P', 'C', '+' }; return searchForBytes(image, size, signature, 4, 2); } Quote Link to comment Share on other sites More sharing options...
wallaby Posted September 6, 2016 Author Share Posted September 6, 2016 RWRITE0 thru RWRITE3 let you assign any value you want, just don't make them all 0s or that will disable the LFSR. As an example: RWRITE0 = 11 RWRITE1 = 9 RWRITE2 = 19 RWRITE3 = 66 A 32 bit random number generator is perfect, but how do you access the registers like RWRITE from bB? Or is it more practical to use assembly and make a macro or something? Finally, a bit off topic - I'd love to use C to program the Atari but one thing that makes bB so attractive is the multitude of examples and help the community provides. Also, Random Terrain's website with just about everything you need all on one page. Are there any resources for C that can kick start Atari development? What are the pros and cons to using C and does programming directly on the arm chip grant you a huge computing resource? Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted September 6, 2016 Share Posted September 6, 2016 A 32 bit random number generator is perfect, but how do you access the registers like RWRITE from bB? Or is it more practical to use assembly and make a macro or something? While I'm not well versed with bB, the examples I gave are what I think you'd use in bB. If those don't work then I'm sure somebody more familiar with bB will step up and show how to access those registers now that they know what they're called. Finally, a bit off topic - I'd love to use C to program the Atari but one thing that makes bB so attractive is the multitude of examples and help the community provides. Also, Random Terrain's website with just about everything you need all on one page. Are there any resources for C that can kick start Atari development? What are the pros and cons to using C and does programming directly on the arm chip grant you a huge computing resource? Using C gives you a lot of extra resources; however, you still need to write 6507 assembly code as the two work together hand-in-hand. It's how I was able to pull off Space Rocks and Stay Frosty 2. There's 3 unfinished games as well, Draconian, Frantic and Timmy. Most of the source for my projects has been made available in my blog. To make it easier to find things look in the right hand column for the section labeled Categories. I'd recommend you first start out with my series Collect, which covers writing a 2K game from scratch using 6507 assembly. After you've familiar with that, then check out my DPC+ ARM Development series. Do note it's currently on hiatus as we've been busy working on Bus Stuffing which will eventually let us do things that we can't even do with DPC+. Quote Link to comment Share on other sites More sharing options...
wallaby Posted September 7, 2016 Author Share Posted September 7, 2016 Looks like they're called the same in bB. I tried it before and got an error, but I just made a few asm macros and it turns out they're directly accessible in bB using those names. That was excellent, thanks. I also found those comments in the .txt file that bB generates which was a big help too. Quote Link to comment Share on other sites More sharing options...
+SpiceWare Posted September 7, 2016 Share Posted September 7, 2016 Looks like they're called the same in bB. I tried it before and got an error, but I just made a few asm macros and it turns out they're directly accessible in bB using those names. That was excellent, thanks. I also found those comments in the .txt file that bB generates which was a big help too. Great! Those comments are from the DPCplus.h file; though I think the rest of the registers, those not related to random numbers, will not be very useful for bB programmers. Quote Link to comment Share on other sites More sharing options...
Recommended Posts
Join the conversation
You can post now and register later. If you have an account, sign in now to post with your account.
Note: Your post will require moderator approval before it will be visible.