Slight oversight on my part... Those objects have 0 for their collision property, because they do their own detection, so you should ignore objects whose collision property is 0. Attacking your own shield? XD
I need a better handle of cpu logic as a whole. I'm looking at commands like beq and and bpl and, while I know what the commands are acronyms for, I don't understand how they work in computer logic. For example.. Code (ASM): move.b (a0),d0 ; get the object's ID beq.s + ; if it's obj00, skip it BRanch if Equal to what?. Where can I go/what can I read to bone up on this kind of stuff?
There's a space called the CCR (Condition Code Register), whenever a command is run be it move, sub, add, mul, etc, they set, clear or ignore up to five bits in the CCR which are as followed; X, N, Z, Y and C, depending on the conditions met (See an MC68k referrence manual for more information about which bits are set, cleared and ignored by which commands). As an example in your code, that move command, if the result in d0 is 0 (Zero), it'll set the Z flag, if it's not, it will clear the Z flag, beq and bpl reads this Z flag and branches depending on whether it's set or clear.
To add to that, CMP is just a subtraction that doesn't store the result (while still setting the CCR flags). Therefore, when you have something like this: Code (ASM): cmp.w d1,d0 beq.s + it means, "if d0 - d1 = 0, branch" (which has the same effect as "if d0 = d1, branch"). When in doubt, it's zero! :v: The reference manuals are on Freescale's website.
Maybe this will help. This is how the Homing attack code in my hack looks for objects to home in on: Code (ASM): lea (Object_RAM+$400).w,a1 ; check obj ram ($FFFFB400) moveq #$6F,d6 ; search to end of table tst.w (Two_player_mode).w ; 2p mode check beq HomingAttack_Loop ; branch if equal moveq #$27,d6 ; search to $BF00 exclusive HomingAttack_Loop:; this part checks for objects to home in on tst.b (a1) ; is there an object in this slot? beq HomingAttack_NextObj ; if not, check next object ; here you can add checks for "non collidable" objects move.b collision_flags(a1),d0 ; is the object collidable? beq HomingAttack_NextObj ; if not, branch ; here you can check for any object with collision, like enemies or monitors and.b #$C0,d0 ; is the object an enemy? beq + ; if it is, skip monitor check cmp.b #$26,(a1) ; is the object a monitor? - $3F in S1 I guess, helpful if I want to add this to S1 beq + ; if it is, check the positions of the object bra HomingAttack_NextObj ; Branch to check for the next object in objRAM
I was hoping to be able to figure this out without looking at someone else's code but that's really helpful. For what it's worth, what I was stuck on for a while was figuring out how to start things. The logic I was going through in my head was more or less like that, Hitaxas EDIT: I notice you don't put .s or .b or .w (forgot technical term for now) after any of your bcc commands hitaxas. Why is that?
While (in my opinion) it is a bad programming habit, some assemblers will pick the appropriate one for you if you don't specify that. Personally I always specify that. By the way: .b stands for byte, .w stands for word, .l (which is unusable for bxx jumps, but is usable in other commands such as cmpi) stands for long; .s is an alternate form for .b, it possibly stands for short. Also this.
When working with assembly, you shouldn't trust the acronyms so much. You should get a book or a document that describes what the instructions actually do, because their names alone usually don't say much. It is important that you have a manual that tells you which flags are affected by which instructions and how the instructions behave based on the status of the flags. Knowing these things allows you to write more efficient code, because you won't be doing superfluous comparisons or other unnecessary operations. There are also several interesting tricks that consist in using the instructions for purposes they weren't designed for.
Closest thing I've got to a book is 68k.hax.com and the 68000 manual online. I actually need to download it, since I'll be offline for a little while soon.
While we are talking about this assembler stuff, I figured I could ask you if I understood the flags correct: - C-flag: $2000-$1F00=$100, so something is left and this flag is set. If it'd be $1F00-$2000, it's $FF00, and it isn't set. - V-flag: If you increase a data register, which for example is $7F ($FF signed) and you add something to it, it will restart "on the other end", which means it'll be $80, which is 0 in unsigned format and this flag will be set. - Z-flag: If a RAM adress or data register or whatever is 0, this will be set. - N-flag: If you substract something from something, 7 from 5, it will be -2 ($FE unsigned) and this flag is set. - X-flag: Basically a copy of the C-flag. Was that all correct by me? I'm pretty sure I wrote complete bullshit on the C-flag, but whatever.
Okay, I've started to try a level layout hack in Sonic 2 using the Esrael Sonic Editor II. So far, I've learned do edit visually the tiles, as well as making a playable layout. But there's that borderline, that doesn't allow Sonic to get to the new lower portion I'm adding to Emerald Hill (leaving some "bottomless pits"), that I need to draw in downwards. What's the catch with the borderline? And how can I do to insert objects into the stages with the ESEII?
Simple answer: You can't. ESEII is pretty much outdated due to the fact that split disassemblies are now used more nowadays. Grab yourself a disassembly from Disassemblies and grab SonED2 while you're at it.
Good thing I have SonED2 on my computer (SonED1 came broken to the PC, so I'm stuck with version 2). Well, time to fathom (and research) how to deal with the legenday chimera. Well, I must have Sonic 1 and 2 disassemblies, gonna get Sonic 3K disassemblies now. Thanks for the info.
Let's read the Motorola 68000 Family Programmer's Reference Manual, shall we? X is a copy of C after arithmetic operations, but other instructions like shifts and rotates only affect the C flag, leaving the X flag unchanged. While on some CPU architectures there are operations that work with the carry flag, on the 68000 they work with the extend flag, whose value may "survive" longer (instructions like ADDX, NEGX, etc.). N is set if the most significant bit is set. For byte-sized operations, this is bit 7, for word-sized operations, it's bit 15, and for longword-sized operations, it's bit 31. Z is set if the result is zero. As I recently explained, CMP does a subtraction, sets the flags like a subtraction does but discards the result. The values of V and C may be harder to figure out. Each instruction has a short description of how those flags are set, but sometimes you wonder what's the difference between a carry and an overflow (note that the carry flag is used for borrow in subtraction instructions). In this case, look in table 3-18, on pages 3-18 and 3-19. ? means AND, ? means OR and an overline means NOT. ? has precedence over ? (just like × has precedence over +) and parentheses are used to override precedence — standard stuff. Also read the legend at the end of the table. While you're on those pages, you might be interested in table 3-19 on page 3-19, which explains how each condition code for Bcc/DBcc/Scc is evaluated.
There are a few hacks out there which feature level transitions. Off the top of my mind, Sonic_2:_S3_Edition and Sonic and the Secret Extended Edition. There might be others though.
Has anyone ever written things like that down for other people to learn from? Honestly, certain things are pretty daunting for beginners, and many of the How-Tos on the wiki boil down to copy+paste bonanzas. I'm appreciative all the same, but I'm not really learning anything if I'm just copy and pasting stuff...