Jedd Posted April 20, 2004 Share Posted April 20, 2004 Hey all, I'm trying to make a simple game right now, and it would be a lot easier if I could convert an 8-bit number to it's inverse. So if I had the number #%00101111 it would generate the number #%11010000. How can I do this? Preferably as small as possible, since this will be done to generate the right side of the playfield. Thanks! -J Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 20, 2004 Share Posted April 20, 2004 EOR #$FF EOR (or more commonly known as XOR these days) flips all the bits in the accumulator by the value indicated in the argument. Quote Link to comment Share on other sites More sharing options...
CPUWIZ Posted April 20, 2004 Share Posted April 20, 2004 EOR #$FF Quote Link to comment Share on other sites More sharing options...
CPUWIZ Posted April 20, 2004 Share Posted April 20, 2004 LOL Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 20, 2004 Share Posted April 20, 2004 BTW you mention drawing the right side of the playfield. The 2600 can mirror or reflect the values used in PF0-2 automatically if you want (so you don't need to reload them mid-scanline). Quote Link to comment Share on other sites More sharing options...
Jedd Posted April 20, 2004 Author Share Posted April 20, 2004 Sweet. Thanks! Hopefully I can get this game working, it's going to be a simple tunnel vertical-scrolling game. Also...a side note, how can I generate a random number? Like 0, 1, or 2? If I can't generate random numbers, all the levels will need to be pre-made, and that would get old after 1 play. -J Quote Link to comment Share on other sites More sharing options...
Jedd Posted April 20, 2004 Author Share Posted April 20, 2004 BTW you mention drawing the right side of the playfield. The 2600 can mirror or reflect the values used in PF0-2 automatically if you want (so you don't need to reload them mid-scanline). Yah I know, but then it wouldn't really be like turns, it would just make the space bigger and smaller. By inverting it, I can make it so the playfield makes turns. -J Edit: Oh and just so you know, I'm not even going to use PF0, it will just be filled with #%11111111 the whole time. This is my first attempt at a game and I want to keep it simple. Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 20, 2004 Share Posted April 20, 2004 Random numbers in computers are never really random. The best thing you could do is grab a value from an event that is likely to be highly-variable (like the amount of time of when the program started to when the reset button was actually pressed to begin the game) and use that value in a few other operations to make it "seem" like it's a random event. Use some ram locations that are constantly shifting and EOR them together, for example. Quote Link to comment Share on other sites More sharing options...
Jedd Posted April 20, 2004 Author Share Posted April 20, 2004 Bummer there's no random number generator. So do something like, see how long it takes before you hit a button on the intro screen, then from that look up another location, grab some bytes there to look up another location, and keep going on like that? Seems more like chaotic than random. I'll figure something out. Thanks! -J Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 20, 2004 Share Posted April 20, 2004 Edit: Oh and just so you know, I'm not even going to use PF0, it will just be filled with #%11111111 the whole time. This is my first attempt at a game and I want to keep it simple. Just so you know...only the top 4 bits saved to PF0 actually appear on-screen. PF1 and PF2 use the entire 8 bits tho. And PF1 is reversed. Saving to those 3 registers creates the left side of the scanline, and the playfield control register is used if you want to mirror or flip. If you want the other side to be unique, you'll need to store new values to PF0-2 before the scanline is drawn. Anyway, here's the bitpattern of PF0 to PF2: PF0: +$10 +$20 +$40 +$80 ....pixels 0 (the edge of the screen) to 3 PF1: +$80 +$40 +$20 +$10 +$08 +$04 +$02 +$01 ...pixels 4 thru 11 PF2: +$01 +$02 +$04 +$08 +$10 +$20 +$40 +$80 ....pixels 12 thru 19 (the center) Add up the values shown depending on where you want your pixels to appear, and that's the value you need for the appropriate register. Quote Link to comment Share on other sites More sharing options...
EricBall Posted April 20, 2004 Share Posted April 20, 2004 One of the simplest Pseudo-Random Number Generator (PRNG) is a Linear Feedback Shift Register (LFSR). This is a routine which takes the last value of the PRNG, shifts it by a bit, then uses the bit shifted out to determine whether to XOR the PRNG with a value. Here is an example: ; simple 8 bit LFSR (RANDOM is a byte in Zero Page RAM) RAND LDA RANDOM BEQ XSEED LSR BCC SRAND XSEED EOR #$A9 SRAND STA RANDOM RTS In Skeleton+ this subroutine is called once per frame including during the title and ending screens. Then the code just samples RANDOM as required when a random byte or bit is needed. Some games use multiple LFSRs or incorporate additional "random" inputs like cycling the LFSR an additional time when the player presses a button. But I figure that since the LFSR is "free running" that when the game is started is random enough. LFSRs do have some negatives. First, they have a null value (typically all bits set or cleared) that will not cycle properly. That is why my routine has the extra BEQ at the begining to avoid this problem. This also means that RANDOM will never be zero once the game starts. Simple LFSRs are also predictable and will tend to have sequences of certain values. Depending on how you use your PRNG, this may not be a big issue. Skeleton+ doesn't use the PRNG every frame and typically only uses bits 6 & 7, so this wasn't a concern for me. (But this is why LFSRs are snubbed by the crypto boys who want "real" random number generators.) LFSRs can also be used for other things - like map generation in PitFall! Quote Link to comment Share on other sites More sharing options...
Jedd Posted April 20, 2004 Author Share Posted April 20, 2004 Yeah that's why I'm not going to even mess with PF0. Inverting it would cause it to be blank on the right side. And I know how PF1 and PF2 work. I have no clue what they were thinking when they designed that. Right now the code is set up to have a unique left side and a unique right side. It works pretty well, but it's a lot more complicated to program, and the levels take up more space. I think I'm going to have a pre-made level for the first version of this game, just to keep it simple. Right now I have a level 38 pixels high (19 pixels high per screen) so it's pretty boring. Once I finish the level, programming the game itself shouldn't be too hard, and it will help me a lot with my understanding of sprites. -J Quote Link to comment Share on other sites More sharing options...
Jedd Posted April 20, 2004 Author Share Posted April 20, 2004 One of the simplest Pseudo-Random Number Generator (PRNG) is a Linear Feedback Shift Register (LFSR). This is a routine which takes the last value of the PRNG, shifts it by a bit, then uses the bit shifted out to determine whether to XOR the PRNG with a value. Here is an example: ; simple 8 bit LFSR (RANDOM is a byte in Zero Page RAM) RAND LDA RANDOM BEQ XSEED LSR BCC SRAND XSEED EOR #$A9 SRAND STA RANDOM RTS In Skeleton+ this subroutine is called once per frame including during the title and ending screens. Then the code just samples RANDOM as required when a random byte or bit is needed. Some games use multiple LFSRs or incorporate additional "random" inputs like cycling the LFSR an additional time when the player presses a button. But I figure that since the LFSR is "free running" that when the game is started is random enough. LFSRs do have some negatives. First, they have a null value (typically all bits set or cleared) that will not cycle properly. That is why my routine has the extra BEQ at the begining to avoid this problem. This also means that RANDOM will never be zero once the game starts. Simple LFSRs are also predictable and will tend to have sequences of certain values. Depending on how you use your PRNG, this may not be a big issue. Skeleton+ doesn't use the PRNG every frame and typically only uses bits 6 & 7, so this wasn't a concern for me. (But this is why LFSRs are snubbed by the crypto boys who want "real" random number generators.) LFSRs can also be used for other things - like map generation in PitFall! Ok only about half of that makes sense, but thanks for your help! Btw, is there a hacked version of Pitall with randomly generated maps? That would be pretty cool. (never know what to expect). -J Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 20, 2004 Share Posted April 20, 2004 Nono...what he meant was that the maps in Pitfall! are random. But since the generator works in a predicatable pattern, it's the same every time you play it. Amazing, no? BTW if you only want a smaller range (say a number from 0 to 3), you can use AND to throw away the bits not needed (AND #$03 in this example). Quote Link to comment Share on other sites More sharing options...
Jedd Posted April 20, 2004 Author Share Posted April 20, 2004 I only need a number 0-2. What exactly does AND do? I read in the other tutorial, Atari 2600 101, that the extra 4 bits in a 4-bit register where not only unused, but attained random values somehow. Can I use those numbers? -J Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 20, 2004 Share Posted April 20, 2004 Operators: The AND instruction signifies which bits you want to keep. AND#$FF for example would seemingly have no effect at all...since all bits in the original are kept, the value in the accumulator would remain the same. AND#$00 on the other hand would always return a value of zero (no bits are kept). The OR (or ORA) instruction keeps bits that are set in either the accumulator OR the argument. If A holds $0F and you ORA#$F0...it would become $FF. $F1 (all the upper bits +the lowest bit) ORA#$F2 (all the upper bits+the next-to lowest bit) = $F3 (all the upper bits+the two lowest bits) And XOR you already know...every bit just changes from 0 to 1 or visa-versa. The bits you want to flip you just specify in the argument. Quote Link to comment Share on other sites More sharing options...
Jedd Posted April 20, 2004 Author Share Posted April 20, 2004 Ok. I understand how they work now, thanks. But I don't get how you can store the new number into a register or PF1 or something. I don't even understand where in the code it says which byte you are editing. I know what EOR #$FF does, but that's not very usefull. How can I invert a different byte? EOR a? EOR x? EOR PF1? And how do I then store that back into the number? STA PF1? Or is it automatically done? I've only been doing this for 3 weeks, so please bare with me. -J Quote Link to comment Share on other sites More sharing options...
EricBall Posted April 21, 2004 Share Posted April 21, 2004 Jedd, it sounds like you are missing some basic concepts around registers and memory. The 6502 has 3 "general purpose" registers: A, X & Y. (And 3 special purpose registers: PC, SP and PS.) All instructions use at least one of these registers. EOR #$FF means "take the value in the A register, bitwise exclusive or it with the value $FF and store the resulting value back into the A register". PF1 is a TIA register which is memory mapped to address $000E. So a STA $000E instruction stores the value in the A register into TIA register PF1. Other CPUs have more registers and may specify more than one register per instruction. Quote Link to comment Share on other sites More sharing options...
Jedd Posted April 21, 2004 Author Share Posted April 21, 2004 Awesome, thanks. So to invert PF1, I would do this... LDA PF1 EOR #%11111111 STA PF1 ...? Is that right?? Thanks for you help. Hey again. I made a scrolling program but nothing works. A pixel moves back and forth at the top while the rest of the playfeild stays the same, but is also the wrong image. I must have done something wrong. Any ideas? Thanks -J Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 21, 2004 Share Posted April 21, 2004 No, you can't load the value from PF1...those memory locations are write-only. To load the value that you want to invert, you would need to load it from a user ram location or from a table in rom. Clarification: #$FF is not a memory location. The # symbol means that you want to work with the value that is already in the register (the accumulator in this case...since AND, ORA, and EOR work with that register). Quote Link to comment Share on other sites More sharing options...
Happy_Dude Posted April 21, 2004 Share Posted April 21, 2004 #$FF is not a memory location. The # symbol means that you want to work with the value that is already in the register (the accumulator in this case...since AND, ORA, and EOR work with that register). Actually # notifies the assembler to use the value $FF and not the Memory location $FF (imediate addressing) Either way those instructions always work on the accumulator no matter where they get their values from. Quote Link to comment Share on other sites More sharing options...
Nukey Shay Posted April 21, 2004 Share Posted April 21, 2004 Oops...I didn't mean to imply that you could use a format of those instructions which would not affect the accumulator. That's not what I was trying to say. I thought that the part in the () made that clear, but I see how it could be misunderstood. Quote Link to comment Share on other sites More sharing options...
Jedd Posted April 21, 2004 Author Share Posted April 21, 2004 Ok then, I'll just load PF1 and PF2 from my array (can I use the word array in Asm?), rather than PF1 and PF2 themselves. If I still can't figure it out, I'll post my code later today. -J Quote Link to comment Share on other sites More sharing options...
Happy_Dude Posted April 21, 2004 Share Posted April 21, 2004 (can I use the word array in Asm?), Only when refering to an array ........ Quote Link to comment Share on other sites More sharing options...
Tom Posted April 21, 2004 Share Posted April 21, 2004 (can I use the word array in Asm?), Of course you can. Btw: As all Real Programmers know, the only useful data structure is the Array. Strings, Lists, Structures, Sets-- these are all special cases of arrays and can be treated that way just as easily without messing up your programming language with all sorts of complications. read the whole text here: http://www.pbm.com/~lindahl/real.programmers.html 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.