Jump to content
IGNORED

Inverting Bytes


Jedd

Recommended Posts

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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!

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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).

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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.

Link to comment
Share on other sites

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

Link to comment
Share on other sites

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).

Link to comment
Share on other sites

#$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.

Link to comment
Share on other sites

(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

 

:)

Link to comment
Share on other sites

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.

Guest
Reply to this topic...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...