Code: Select all
ror a
ror a
and #$01
beq +
;code for a value of 1
+
;code for a value of 0
Moderator: Moderators
Code: Select all
ror a
ror a
and #$01
beq +
;code for a value of 1
+
;code for a value of 0
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:unregistered wrote:But the result wouldn't be a 1 or a zero... But, beq only focuses on a 0. So... is that right?
Code: Select all
;copy bit 2 to the carry flag
and #%00000100
cmp #%00000100
tokumaru[color=white],[/color] [url=http://nesdev.com/bbs/viewtopic.php?t=7451&postdays=0&postorder=asc&start=360]on page 25[/url][color=white],[/color] wrote: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...unregistered wrote:How do I know if the something IS water? How do I check the tile number?
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.
This is good... and it works becausetokumaru wrote: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:unregistered wrote:But the result wouldn't be a 1 or a zero... But, beq only focuses on a 0. So... is that right?Then you can shift the bit into some variable using ROR or ROL, or do whatever else you want with it.Code: Select all
;copy bit 2 to the carry flag and #%00000100 cmp #%00000100
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.unregistered wrote:a)The AND puts 4 into 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.b)then... the CMP puts (Accumulator - Memory) in the Accumulator?
Code: Select all
#%00000000
^^^^^^^^
||||||||
BIT#: 76543210
#%00000000
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)tokumaru wrote:if the accumulator is 4, the subtraction will "succeed" (i.e. there will be no underflow) and the carry will be set.
Kasumi, thanks for helping us! 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...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.
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.Code: Select all
#%00000000 ^^^^^^^^ |||||||| BIT#: 76543210 #%00000000
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.
You know how sbc works, right?unregistered wrote: No underflow?
Code: Select all
sbc foo
Code: Select all
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
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.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...
An overflow is when the result is too large to be represented by the accumulator, and an underflow is when it's too small.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)
I often put my flags in the top 2 bits as well.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.
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 wrote:First disable rendering... by writing the relevant bits to $2000
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.unregistered wrote: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 wrote:First disable rendering... by writing the relevant bits to $2000
When you say level's index that could be 1 for level1 and 2 for level2 right?tokumaru[color=orange], from [url=http://nesdev.com/bbs/viewtopic.php?p=85297#85297]page 27[/url],[/color] 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:
Then you can read the address for the current level and put it in a pointer using the level's indexCode: Select all
MetatileCollisionAdresses: .dw MetatileCollisionLevel1, MetatileCollisionLevel2, MetatileCollisionLevel3
MetatileCollision isnt set up for an address of 2 bytes...:
Code: Select all
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
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.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: Select all
;get collision information lda (MetatileCollision), y