It is currently Wed Jan 24, 2018 1:12 am

All times are UTC - 7 hours





Post new topic Reply to topic  [ 1394 posts ]  Go to page Previous  1 ... 27, 28, 29, 30, 31, 32, 33 ... 93  Next
Author Message
 Post subject:
PostPosted: Sat Dec 31, 2011 2:19 pm 
Offline
User avatar

Joined: Thu Apr 23, 2009 11:21 pm
Posts: 816
Location: cypress, texas
If I have 00001111 in the accumulator... how could I check the bit value of the ones? Like how would I say check the value of bit #2? Is there a faster way to do this than

Code:
    ror a
    ror a
    and #$01
    beq +
      ;code for a value of 1
    +
      ;code for a value of 0

Does that even work? I think it does. :oops:


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 31, 2011 2:23 pm 
Offline
User avatar

Joined: Fri Nov 19, 2004 7:35 pm
Posts: 3987
How about just "AND #$04" to check bit 00000100?

_________________
Here come the fortune cookies! Here come the fortune cookies! They're wearing paper hats!


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 31, 2011 2:28 pm 
Offline
User avatar

Joined: Thu Apr 23, 2009 11:21 pm
Posts: 816
Location: cypress, texas
Dwedit wrote:
How about just "AND #$04" to check bit 00000100?


But the result wouldn't be a 1 or a zero... But, beq only focuses on a 0. So... is that right?

edit: That's brilliant! Thanks Dwedit! :D Have a happy new year! :)


Top
 Profile  
 
 Post subject:
PostPosted: Sat Dec 31, 2011 5:10 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10233
Location: Rio de Janeiro - Brazil
unregistered wrote:
But the result wouldn't be a 1 or a zero... But, beq only focuses on a 0. So... is that right?

As you probably have realized, if the result is not 0 you know that the bit is set. If you wanted to copy any bit to the carry flag (sometimes we do that when rearranging bits) you could use an AND followed by a CMP:
Code:
   ;copy bit 2 to the carry flag
   and #%00000100
   cmp #%00000100

Then you can shift the bit into some variable using ROR or ROL, or do whatever else you want with it.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Jan 04, 2012 4:21 pm 
Offline
User avatar

Joined: Thu Apr 23, 2009 11:21 pm
Posts: 816
Location: cypress, texas
tokumaru, on page 25, wrote:
unregistered wrote:
How do I know if the something IS water? :? How do I check the tile number?

One of the ideas we had consisted in using 1 bit to select between water or air for the empty tiles, and 3 bits for the type of the solid tiles. In this case it would be easy to know if something is water, but since you decided to use the tile index...

Well, your screenArray only has the basic collision info, it doesn't say which tiles each block uses. The only way is to make screenArray hold the index of the metatiles instead of the collision info. That way, whenever you wanted to test for collisions, you'd have to get the metatile index at the position you want and use that to fetch the collision info from a table. With the same index you can easily access the tile indexes too. It's a bit more indirect, but that's not too bad.



The last part has me confused. If screenArray held "the index of the metatiles instead of the collision info" would that destroy our library and collision files? That would be terrible! My sister has done so many of them so far. :shock:

That first thing you mentioned about "using 1 bit to select between water or air for the empty tiles, and 3 bits for the type of the solid tiles." Since we have two extra bits could we set one of them to select between water or air for the empty tiles by itself (without the 3 bits for the solid type tiles)? Then wouldn't it be much easier to know if something is water? :oops:


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 12, 2012 5:32 pm 
Offline
User avatar

Joined: Thu Apr 23, 2009 11:21 pm
Posts: 816
Location: cypress, texas
tokumaru wrote:
unregistered wrote:
But the result wouldn't be a 1 or a zero... But, beq only focuses on a 0. So... is that right?

As you probably have realized, if the result is not 0 you know that the bit is set. If you wanted to copy any bit to the carry flag (sometimes we do that when rearranging bits) you could use an AND followed by a CMP:
Code:
   ;copy bit 2 to the carry flag
   and #%00000100
   cmp #%00000100

Then you can shift the bit into some variable using ROR or ROL, or do whatever else you want with it.


:) This is good... and it works because
a)The AND puts 4 into the accumulator...
b)then... the CMP puts (Accumulator - Memory) in the Accumulator?
c)so now the Accumulator has a 0. Does that 0 clear the Carry flag?
d) ...I dont know why this works...Could you help me please?


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 12, 2012 6:14 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10233
Location: Rio de Janeiro - Brazil
unregistered wrote:
a)The AND puts 4 into the accumulator...

No, it ANDs whatever is in the accumulator with 4, the result will only be 4 if bit 2 was set in the original value, otherwise it will be 0.

Quote:
b)then... the CMP puts (Accumulator - Memory) in the Accumulator?

No, CMP does not change the value of the accumulator. It does calculate A - 4, but the result is not stored anywhere. What matters to us is the value of the carry after this subtraction: if the accumulator is 4, the subtraction will "succeed" (i.e. there will be no underflow) and the carry will be set. If the accumulator is 0, the subtraction will cause an underflow, clearing the carry. This causes the carry to become whatever bit 2 was in the first place, so we have effectively "copied" bit 2 into the carry flag.


Top
 Profile  
 
 Post subject:
PostPosted: Thu Jan 12, 2012 7:39 pm 
Offline
User avatar

Joined: Wed Apr 02, 2008 2:09 pm
Posts: 1059
Tokumaru covered CMP, but here's a little more explanation on what AND and the other bitwise operators (hey, why not?) do, and why what Dwedit suggested works:

AND (like ORA and EOR) at a basic level gives an output of 1 bit from 2 input bits. Order doesn't matter in any of them, so there are three cases.

1. Both bits are 0.
2. Both bits are 1
3. 1 bit is 1, and the other is 0.

AND gives an output of 1 if both input bits were 1. (if input bit 1 is 1 [true] AND input bit 2 is 1 [true], the result is true.) See how it got its name? :)

So, AND will only return 1 in case 2, otherwise it gives 0.

ORA gives an output of 1 if either input bit is one. (If input bit 1 is 1 [true] OR input bit 2 is 1[true], the result is true.) See how it got its name?

So ORA will return 1 in every case except case 1. It will return 0 in case 1.

EOR (Exclusive OR) gives an output of 1 if EXACTLY one of the input bits is 1. (If input 1 and ONLY input is 1 [true], the result is true. If input 2 and ONLY input 2 is 1[true], the result is true)

So EOR will return 1 only in case 3, otherwise it gives 0.

Now, at a basic level they work one bit at a time. The instructions work a byte at a time with corresponding bits in a byte.

Code:
     #%00000000
       ^^^^^^^^
       ||||||||
BIT#:  76543210
     #%00000000

They check and return the result of bits 7 in each byte, and while that check is happening what's in bits 6-0 doesn't matter. Then it does bits 6, and while that check is happening what's in bits 7 and 5-0 doesn't matter. Etc.

AND is useful for checking the status of a specific bit, because by definition of AND, a bit with a 0 in either byte will return 0.

So if you AND with a number that has 7 bits as 0, the result of those seve bits will be 0. That means the bit you left 1 in the AND determines whether the accumulator is 0, or non-0.

Another use for AND is clearing a bit (setting it to 0). #%01111111 will clear the leftmost bit without changing the others. The 0 is guaranteed to clear the high bit because the 0 means both bits CAN'T be 1, and the 7 ones guarantee the other bits won't change.

EOR is useful for toggling a bit (0->1 or 1->0). This is because a 0 in an EOR is guaranteed to not change the bit it is being EOR'd with, while a 1 in an EOR is guaranteed TO change the bit it is being EOR'd with.

ORA is useful for setting a bit to 1. This is a because a 1 is guaranteed to give a result of 1, while a 0 will never change the bit you are ORA'ing with.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 15, 2012 4:47 am 
Offline
User avatar

Joined: Thu Apr 23, 2009 11:21 pm
Posts: 816
Location: cypress, texas
tokumaru, thank you so much for helping me with this! :D
tokumaru wrote:
if the accumulator is 4, the subtraction will "succeed" (i.e. there will be no underflow) and the carry will be set.

No underflow? So water will not flow under the subtraction and that sets the carry? (trying to get you to teach me more about "underflow" - im interested) :)

----
tried to make this easier to read... for me at least... just added colors :)
Kasumi wrote:
Tokumaru covered CMP, but here's a little more explanation on what AND and the other bitwise operators (hey, why not?) do, and why what Dwedit suggested works:

AND (like ORA and EOR) at a basic level gives an output of 1 bit from 2 input bits. Order doesn't matter in any of them, so there are three cases.

1. Both bits are 0.
2. Both bits are 1
3. 1 bit is 1, and the other is 0.

AND gives an output of 1 if both input bits were 1. (if input bit 1 is 1 [true] AND input bit 2 is 1 [true], the result is true.) See how it got its name? :)

So, AND will only return 1 in case 2, otherwise it gives 0.

ORA gives an output of 1 if either input bit is one. (If input bit 1 is 1 [true] OR input bit 2 is 1[true], the result is true.) See how it got its name?

So ORA will return 1 in every case except case 1. It will return 0 in case 1.

EOR (Exclusive OR) gives an output of 1 if EXACTLY one of the input bits is 1. (If input 1 and ONLY input is 1 [true], the result is true. If input 2 and ONLY input 2 is 1[true], the result is true)

So EOR will return 1 only in case 3, otherwise it gives 0.

Now, at a basic level they work one bit at a time. The instructions work a byte at a time with corresponding bits in a byte.

Code:
     #%00000000
       ^^^^^^^^
       ||||||||
BIT#:  76543210
     #%00000000

They check and return the result of bits 7 in each byte, and while that check is happening what's in bits 6-0 doesn't matter. Then it does bits 6, and while that check is happening what's in bits 7 and 5-0 doesn't matter. Etc.

AND is useful for checking the status of a specific bit, because by definition of AND, a bit with a 0 in either byte will return 0.

So if you AND with a number that has 7 bits as 0, the result of those seve bits will be 0. That means the bit you left 1 in the AND determines whether the accumulator is 0, or non-0.

Another use for AND is clearing a bit (setting it to 0). #%01111111 will clear the leftmost bit without changing the others. The 0 is guaranteed to clear the high bit because the 0 means both bits CAN'T be 1, and the 7 ones guarantee the other bits won't change.

EOR is useful for toggling a bit (0->1 or 1->0). This is because a 0 in an EOR is guaranteed to not change the bit it is being EOR'd with, while a 1 in an EOR is guaranteed TO change the bit it is being EOR'd with.

ORA is useful for setting a bit to 1. This is a because a 1 is guaranteed to give a result of 1, while a 0 will never change the bit you are ORA'ing with.

Kasumi, thanks for helping us! :D The logic surrounding your cases is interesting. :) : ) There are shortcuts or cycles that can be saved, right? I have tried to think of one, but I can't think of anything... :oops:


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 15, 2012 11:22 am 
Offline
User avatar

Joined: Wed Apr 02, 2008 2:09 pm
Posts: 1059
unregistered wrote:
No underflow?

You know how sbc works, right?
Let's assume the carry is set before the sbc. Let's assume we're working with unsigned numbers. (#$FF = 255. Signed would mean #$FF = -1)
So this
Code:
  sbc foo

will subtract foo from the accumulator. If the accumulator ends up as a larger number than what you started with (example: 0 - 1 = 255), the carry is cleared. That's underflow. If there was no underflow, the carry stays set.

(Overflow is the term for addition when you end up with a number lower than what you started with [example: 255+1 = 0])

CMP does nearly the exact same thing as SBC, except for two things:
1. CMP doesn't care about the carry flag's status before it's run. It could be cleared and an extra one would not be subtracted.
2. CMP doesn't store the result of the subtraction in the accumulator. A never changes.

CMP (or even SBC) works to compare numbers because cmping a larger number guarantees the carry will be clear, and vice versa. Think: If you subtract a larger number from a smaller number you will always pass 0. (And wrap to #$FF on the 6502.)
If the number you subtract is the same, the carry stays sets and the zero flag is set because the result is 0.

What tokumaru was suggesting works because anything cmp'd with 0 that is not 0 gives a result that is not 0. And anything that is not zero clears the 0 flag.

Code:
lda byte
and #%00010000;This guarantees the accumulator is either
;#%00000000 (beq would branch)
;or
;#%00010000 (bne would branch)

;If you cmp #%00010000, it actually reverses that for reasons that should be clear given the above explanations.
cmp #%00010000
;if the accumulator has #%00000000 bne would branch. #%00000000 - #%00010000 is not 0.
if the accumulator has #%00010000 beq would branch. #%00010000 - #%00010000 is 0


unregistered wrote:
There are shortcuts or cycles that can be saved, right? I have tried to think of one, but I can't think of anything... :oops:

Optimization is my favorite business, but it's a tricky, possibly dangerous one that's always specific to what you want to do. Get your code to work first, then make it fast.

Quick tips:
Even though I just typed a book describing it, avoid cmping to reverse the 0 flag. :lol: If you just use the other branch, you can avoid the cmp which always makes sense to me.

You shouldn't ever have to and #%10000000 to check that bit because bpl and bmi already check that highest bit when it's loaded

BIT puts the highest two bits (marked X) #%XXYYYYYY into flags you can branch on, but only for variables stored in a static place.

Because of that I always place the two things the need to be checked most often in those bits when I write data formats.


Top
 Profile  
 
 Post subject:
PostPosted: Sun Jan 15, 2012 12:03 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10233
Location: Rio de Janeiro - Brazil
I know Kasumi already explained a lot but I still want to say a few things.

unregistered wrote:
No underflow? So water will not flow under the subtraction and that sets the carry? (trying to get you to teach me more about "underflow" - im interested) :)

An overflow is when the result is too large to be represented by the accumulator, and an underflow is when it's too small.

For unsigned numbers, an overflow is when an addition results in a number larger than 255, and an underflow is when the result of a subtraction is less than 0. For signed numbers, an overflow means an addition with a result larger than 127 and an underflow is a subtraction with a result of less than -128.

Kasumi wrote:
Because of that I always place the two things the need to be checked most often in those bits when I write data formats.

I often put my flags in the top 2 bits as well.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 01, 2012 7:40 pm 
Offline
User avatar

Joined: Thu Apr 23, 2009 11:21 pm
Posts: 816
Location: cypress, texas
Thank you Kasumi and tokumaru! :D

Kasumi wrote:
First disable rendering... by writing the relevant bits to $2000

How do I disable rendering? The 7th bit of $2000 starts or stops an NMI from running at the start of vertical blanking. Does that somehow disable rendering? :?


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 01, 2012 7:49 pm 
Offline
User avatar

Joined: Sat Feb 12, 2005 9:43 pm
Posts: 10233
Location: Rio de Janeiro - Brazil
unregistered wrote:
Kasumi wrote:
First disable rendering... by writing the relevant bits to $2000

How do I disable rendering? The 7th bit of $2000 starts or stops an NMI from running at the start of vertical blanking. Does that somehow disable rendering? :?

Kasumi probably meant $2001, where bits 3 and 4 enable or disable background and sprite rendering. To disable rendering you have to clear both bits.

Bit 7 of $2000 controls whether NMIs fire or not when VBlank starts, but the rendering process isn't affected at all.


Top
 Profile  
 
 Post subject:
PostPosted: Wed Feb 01, 2012 8:05 pm 
Offline
User avatar

Joined: Thu Apr 23, 2009 11:21 pm
Posts: 816
Location: cypress, texas
tokumaru, thank you so much! :D


Top
 Profile  
 
 Post subject:
PostPosted: Thu Feb 02, 2012 2:26 pm 
Offline
User avatar

Joined: Thu Apr 23, 2009 11:21 pm
Posts: 816
Location: cypress, texas
tokumaru, from page 27, wrote:
Do you want to use different data for each level or something like that? If that's the case, then the answer is the indirect indexed addressing mode (i.e. LDA ($XX), Y). With that addressing mode you use pointers to define the tables that will be read, and you can alter the pointers as much as you want.

For example, you could have a different name for each collision table (or whatever table you want), and then make a table with all the addresses:

Code:
MetatileCollisionAdresses:
   .dw MetatileCollisionLevel1, MetatileCollisionLevel2, MetatileCollisionLevel3

Then you can read the address for the current level and put it in a pointer using the level's index

When you say level's index that could be 1 for level1 and 2 for level2 right?

Quote:
:

Code:
   lda LevelIndex ;get the level's index
   asl ;multiply by 2 because each address is 2 bytes
   tax ;use that as an index into the table of addresses
   lda MetatileCollisionAdresses+0, x ;copy the low byte
   sta MetatileCollision+0
   lda MetatileCollisionAdresses+1, x ;copy the high byte
   sta MetatileCollision+1


MetatileCollision isnt set up for an address of 2 bytes... :?

Quote:
Then you can use indirect indexed addressing to read the data, instead of what we had before. The only real difference is that now you'll have to use Y as your index register, because this addressing mode doesn't work with X:

Code:
   ;get collision information
   lda (MetatileCollision), y



I'm attempting to use this, for the first time, it's kind of confusing and kind of something to learn from. Hope it becomes less of the former and more of the latter; it will. :)


Top
 Profile  
 
Display posts from previous:  Sort by  
Post new topic Reply to topic  [ 1394 posts ]  Go to page Previous  1 ... 27, 28, 29, 30, 31, 32, 33 ... 93  Next

All times are UTC - 7 hours


Who is online

Users browsing this forum: No registered users 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