What I wanna know is how the conditions work. That BNE (branch if not equal)... what are we comparing, and what are we comparing it to? There's no CMP or TST instructions. I've looked everywhere and can't find an explanation for this.
Certain instructions (and, sub, and some others I can't think of) test the Z-flag when executed, essentially doubling as a tst (which checks for zero). You can do a conditional branch immediately after to save a few cycles. What that's doing is, after the AND instruction, branching if the result is NOT zero (hence the bne). It took me a while to figure out you could do this, too—I believe it was drx who told me about it. If you're optimizing for speed in the strictest sense of the word, then such a thing is important to keep in mind. On a side note, we have an Code (ASM): tag which will syntax-highlight and preserve tabbing for M68k code, which I think you'll find much better to use than [quote]. :(
Code (ASM): cmpi.b #$1E,anim_frame(a0) bcs.s Obj01_MdNormal What about that -- it branches if the carry bit is set. I'm confused as to what the carry bit has anything to do with the CMPI instruction. What is this portion actually doing in English?
Look at this wiki page: SCHG:68000 Instruction Set. At the bottom, the condition codes are described, with relational operators to help. So according to this, CS means "less than" (unsigned comparison).
I'm blind—I used that page to look up the name of the Z-flag (wasn't sure to refer to bit or flag, so I just said flag =P) and I never noticed the headers for those conditional matchups. I think I'll convert that section into a proper table so it's easier to work out.
You're right, I didn't realize the conditional match-ups there either. But this works. Okay another question... I know a0 generally points to the object we're currently dealing with, but what address is stored in a1? Reason I'm asking is there's this instance: Code (ASM): add.w x_pos(a0),d1 sub.w x_pos(a1),d1
I believe that, when dealing with Sonic, a1 is the address of the object that he's currently standing on. Correct me if I'm wrong, though; it may be Tails instead.
If you want to be 100% sure, backtrack the code until you see a lea something,a1. Inside an object's code, a1 should be explicitly initialized with lea somewhere before being used.
This is not quite correct, actually those instructions SET the flags, and Bcc both checks them and decides to jump or not to jump..
Here's another question: Code (ASM): andi.b #$C,d0 ; is left/right pressed? bne.s Obj01_Traction ; if yes, branch move.w inertia(a0),d0 beq.s Obj01_Traction We're performing AND on the d0 register. Then (I'm assuming) it branches if the d0 register is not zero. Then it moves "inertia" into the d0 register. This is the part that trips me -- it branches if... d0 is zero? Am I guessing right? EDIT: Also, here's another silly thing I can't figure out: Code (ASM): move.w inertia(a0),d0 beq.s Obj01_Traction bmi.s Obj01_SettleLeft ; slow down when facing right and not pressing a direction ; Obj01_SettleRight: sub.w d5,d0 bcc.s + I get the top portion before the comments, I just included those to ensure everything is in proper context. The half is where I get lost. The BCC will do a branch if the first operand is less than the second operand in the condition. But what operands are we comparing? I see the subtract d5 from d0. I'm assuming d0 is part of the condition, but what is it being compared to... zero?
Exactly. cmp is almost the same as sub, except cmp doesn't store the result anywhere (it only affects the flags), while sub stores the result in its second argument (here, d0). It will branch if d0 is greater than or equal to zero. If you're confused by the carry flag, you can also see it as the borrow flag: if the result of sub is negative, the carry/borrow flag will be set.
Ran into another problem: Code (ASM): move.b angle(a0),d0 add.b d1,d0 move.w d0,-(sp) bsr.w CalcRoomInFront move.w (sp)+,d0 I know what SP is from x86 assembly, but I'm not sure how I'm supposed to read it here. Here's what I'm able to interpret: - move "angle" into the d0 register - add d1 to d0 - push d0 into the stack, then move the stack pointer back one position??? - sub CalcRoomInFront - pop value from stack into d0, then advance the stack pointer one position??? The + and - is guess work. I don't know what they're there for, and that's the problem.
The minus sign before (sp) means to decrement the stack pointer before using it. The plus sign after (sp) means to increment the stack pointer after using it. This is necessary as operations on the stack pointer don't automatically change the stack pointer itself. Predecrementing and postincrementing it is necessary so you won't overwrite previous data.
Hrm. I wasn't sure whether it set the flags or not—from looking at the wiki page, I mean—so I just said "check" to make sure. I mean, it wouldn't set that flag unless the value was zero, right? Damn it all, this topic is making me look dumb XD Oh, and saxman, I believe that is simply pushing an address onto the stack for temporary storage, then putting it back into d0 after CalcRoomInFront has been called. It's a quick alternative to storing up to a long of data without taking up a register.
Yet another question Code (ASM): andi.b #$C0,d0 bne.s return_1A744 I figure the AND must set the Z flag for the BNE to work with. However, my question is does the Z flag get set based on just the bits you AND, or does it get set for the entire d0 register? In other words, is it based on the entire register being zero, or just bits 7 and 6?
It gets set on the entire register being 0, but then the AND modifies the entire register, since ANDing by $C0 implies that all bits other than 7 and 6 will be 0. In other words, just bits 7 and 6 being 0 and the whole register being 0 are the same thing. EDIT: Whoops, misread your question slightly. If by entire register you mean all four bytes of the register, I believe it's just based on the byte that you do AND, not the other bytes of the register. Not sure though.
... rethinking my question, I think I have the answer. Because regardless how the condition works, when you AND d0, you're getting rid of anything below bit 6, so what those bits were make no difference.
Another question: Code (ASM): Sonic_MoveRight: move.w inertia(a0),d0 bmi.s Sonic_TurnRight ; if Sonic is already moving to the left, branch bclr #0,status(a0) beq.s + - move inertia to d0 - if d0 is negative, go to Sonic_TurnRight - clear bit 0 of status - branch if (something) is 0 Is it the status that is being conditioned, or is it d0?
The status. Both bset and bclr first test the bit they're supposed to modify, set flags appropriately and then modify the bit.