Here is another fix from rev 2. Tornado Spindash death. Find: Code (ASM): loc_3A7DE: ...... bsr.w JmpTo27_SolidObject bsr.w loc_3AE3A move.b objoff_2E(a0),d0 move.b status(a0),d1 andi.b #8,d0 ; <---------- Change this line andi.b #8,d1 ; <---------- Change this line eor.b d0,d1 move.b d1,objoff_2E(a0) lea (MainCharacter).w,a1 ; a1=character move.w x_pos(a1),d1 move.w (Camera_X_pos).w,d0 move.w d0,(Camera_Min_X_pos).w Change #8 to #1 and you can do spindash in Tornado. Code (ASM): loc_3A7DE: ...... bsr.w JmpTo27_SolidObject bsr.w loc_3AE3A move.b objoff_2E(a0),d0 move.b status(a0),d1 andi.b #1,d0 ; <---------- Change this line andi.b #1,d1 ; <---------- Change this line eor.b d0,d1 move.b d1,objoff_2E(a0) lea (MainCharacter).w,a1 ; a1=character move.w x_pos(a1),d1 move.w (Camera_X_pos).w,d0 move.w d0,(Camera_Min_X_pos).w And Another bug with Miles in ARZ Boss. If you stand in one arrow with Sonic the arrow will fall, but not with Miles. How To fix Find: Code (ASM): loc_30CCC: ...... btst #3,status(a0) beq.s return_30D02 move.w #$1F,objoff_30(a0) loc_30CF4: and change to Code (ASM): loc_30CCC: ...... ;------------------------------------------------------------------------------- btst #$04, status(A0) beq.s Not_Miles_In_Arrow move.w #$001F, objoff_30(A0) Not_Miles_In_Arrow: ;------------------------------------------------------------------------------- btst #3,status(a0) beq.s return_30D02 move.w #$1F,objoff_30(a0) loc_30CF4: Done.
I wanna touch back on the CPZ boss for a second. There is a minor bug that occurs when you die against the boss. If you or Tails die against the boss, and are under the solid floor, the character will hit the floor and just drop, instead of the proper behavior. Now, I have no problem with said bug... but just noting that its there.
This is not a boss error. This effect can occur in any place with solity over Sonic Head like the location in the following picture. Edit: Using debug and moving left will case the problem reported. This is not necessary a bug (I think), but you can use the following code to disable floor detection while dying. find: Code (ASM): ; loc_1E596: Floor_ChkTile: move.w d2,d0 .... movea.l d1,a1 rts ; =========================================================================== ; precalculated values for Floor_ChkTile ; (Sonic 1 calculated it every time instead of using a table) word_1E5D0: and insert the following code: Code (ASM): ; loc_1E596: Floor_ChkTile: move.w d2,d0 .... movea.l d1,a1 cmpi.b #$06, $0024(A0) bne.s Player_Not_Death cmpi.b #$01, (A0) ; Is Sonic beq.s Player_Death ; cmpi.b #$02, (A0) ; Is Miles bne.s Player_Not_Death ; Player_Death: ; move.l #$FFFF0000, A1 Player_Not_Death: rts ; =========================================================================== ; precalculated values for Floor_ChkTile ; (Sonic 1 calculated it every time instead of using a table) word_1E5D0: This code will point to the first tile in RAM which have no solidity. Since Sonic object can't find solidity will show the dying animation. Edit: Correct check. The Current Character is in A0 Edit: Metal Sonic Fall Bug caused by new code. Edit: 28/05/2019 - Fixed broken links Best regards: ---------------------- Neto.
Sweet deal, Esrael! BTW should the address be A0? or a0? You have A0 and A1 with capital letters. Shouldn't they be lower case? or it doesn't matter?
Disable floor collision while dying - Nice add... I must say. I'm gonna go ahead and see if I can be the one to put this in Sonic 1 on my own... Going to add more to the wiki today.
I might as well post another How to fix monitors' collision There's a bug in Sonic 2 that's not in any other game. The monitor's collision. Well, I say collision, but it's actually fine. It's the touch_collision that's actually wrong. The thing is, in the original Sonic 2 game, it's very hard to spot this bug. Mainly because the monitors are all placed on a flat floor. But whereas many of us have change the level layout of our hacks, some of you may of placed them on hills or slopes (or at the beginning/end of slopes/hills), the bug may be noticeable. The bug? You go straight through the monitors without destroying it. This can be a pain in the ass. The bad thing about it is, if you've placed a monitor on a hill but near a wall, there's a great chance you can go through that wall. This isn't meant to happen obviously. To demonstrate, I have enabled debug and put a monitor in the air. I have now ran and jumped to it. If you come from either side of the monitor, but Sonic going up, you will go through the monitor. That's why this bug is more common on hills/slopes. If you're rolling up a hill into the side of the monitor, chances are you'll go through it without destroying it. Code (ASM): ; loc_3F73C: Touch_Monitor: tst.w y_vel(a0) ; is Sonic moving upwards? bpl.s loc_3F768 ; if not, branch move.w y_pos(a0),d0 subi.w #$10,d0 cmp.w y_pos(a1),d0 bcs.s return_3F78A neg.w y_vel(a0) ; reverse Sonic's y-motion move.w #-$180,y_vel(a1) tst.b routine_secondary(a1) bne.s return_3F78A move.b #4,routine_secondary(a1) ; set the monitor's routine counter rts It does this because there are checks to see if you've hit the bottom of the monitor and if so, to knock the monitor (hit a monitor directly underneath, you know what I mean). But if you go through the sides, it does this check, and it thinks you've missed the bottom when going up to hit it from underneath. Because of this, it branches to an rts. In the code above, it asks if you're moving up and if not, branch away to destroy the monitor. But if moving up, it's doing the check to see if you're going to hit the bottom of the monitor. If you do, it will reverse Sonic's y_vel, and change the routine of the monitor so it can be knocked and fall. BUT, if you miss the bottom, it will branch to "return_3F78A" which is an rts. So, if you're hitting the side of the monitor but in an upwards state, it will branch to the rts; making Sonic go through the monitor and not breaking it. As soon as Sonic's y_vel hits 0 or more (starts to fall down), the monitor will break, because of the very first command. So, we need to make the monitor breakable by hitting the side of it but still going up. Here's how. Go to the code I just showed you above, and change it to this: Code (ASM): ; loc_3F73C: Touch_Monitor: tst.w y_vel(a0) ; is Sonic moving upwards? bpl.s loc_3F768 ; if not, branch move.w y_pos(a0),d0 subi.w #$10,d0 cmp.w y_pos(a1),d0 bcs.s loc_3F768 ; Changed to loc_3F768 instead of return_3F78A neg.w y_vel(a0) ; reverse Sonic's y-motion move.w #-$180,y_vel(a1) tst.b routine_secondary(a1) bne.s return_3F78A move.b #4,routine_secondary(a1) ; set the monitor's routine counter rts All we've done here is changed "return_3F78A" to "loc_3F768". So now, when moving up but hitting the sides of the monitor, instead of it branching to "rts", it branches to the "break monitor" coding! As you can see in the pictures, you will now destroy them. You can still hit the bottom of the monitor and it will knock over. Any other way of hitting the monitor remains unaffected. Done. Additional step you might want to take It's now fixed, but there remains one design flaw (which is actually present in S3K). You know when you hit the monitor, like jumping on it, Sonic's y_vel negates, so he appears to bounce. But with our new fix, if you destroy the monitor from the sides going up, Sonic's y_vel still negates, so he shoots down. It does this in S3K also. To me, this looks unnatural. If you like this, ignore this step. If you don't want Sonic's y_vel to negate when going up, but still to negate when going down, it's simple to do so. Go to "loc_3F768:" and you should see this: Code (ASM): loc_3F768: cmpa.w #MainCharacter,a0 beq.s + tst.w (Two_player_mode).w beq.s return_3F78A + cmpi.b #2,anim(a0) bne.s return_3F78A neg.w y_vel(a0) ; reverse Sonic's y-motion move.b #4,routine(a1) move.w a0,parent(a1) return_3F78A: rts See that? It's negating Sonic's y_vel no matter what when you destroy the monitor. We don't want it to when we're going up, we want to carry on going up. So, change it to this: Code (ASM): loc_3F768: cmpa.w #MainCharacter,a0 beq.s + tst.w (Two_player_mode).w beq.s return_3F78A + cmpi.b #2,anim(a0) bne.s return_3F78A tst.w y_vel(a0) ; is Sonic moving upwards? blt.s + ; if so, branch, we want Sonic to carry on moving up ; So, Sonic is moving down instead? neg.w y_vel(a0) ; reverse Sonic's y-motion, to give him that bounce off the monitor + move.b #4,routine(a1) move.w a0,parent(a1) return_3F78A: rts Now, it checks if you're moving up, and if so, do NOT negate Sonic's y_vel. If you're moving down, it won't branch, and negate his y_vel, giving him his bounce. All done! Cheers, redhotsonic EDIT: I might as well explain. This bug is only in Sonic 2. In Sonic 1, it branches to a subroutine to make the sides of the monitor completely solid, but you can't destroy the monitor still. In Sonic 3 and Knuckles, the coding for hitting the monitor underneath no longer exists. If you hit it underneath in S3K, it will get destroyed. So no bug there.
Although if you implement it in S3K and keep the code to destroy the monitor from below instead of dropping it, not bouncing back down might look a bit funny. My "fix" for this in Sonic 3 Complete is a bit different - if Sonic is on the ground, I use the S&K behaviour, I.e. he can roll through anything regardless of angle. If he's in the air, I use essentially Sonic 1 style behaviour where the sides are treated as solid, because I detest the way you can just jump straight sideways into a monitor in S&K rather than having to go over and land on it. However, I'm not actually too happy with how the solid sides stuff is working, at least my implementation of it (some interesting effects can happen when landing around multiple monitors without rolling), and it may later be reverted to Sonic 2/3A style behaviour in the air, where it's technically possible to jump through - but it's such a rare case in the air that I'm not too troubled by it. Incidentally, I'm pretty sure it is possible to have this bug affect you in vanilla Sonic 3, though you are unlikely to see it without special effort. At the start of CNZ2, there are three monitors suspended in a room a long way above the bottom of the first diagonal barber pole thingy. Tails can fly up there and knock them down to the ground below, which will cause them to land on slopes where it's possible to spindash through them. A question about one of the previous fixes. For the ARZ arrows, you suggest making the code faster by using a cmpi.b to check for Sonic's ducking animation rather than a cmpi.w to check the real frame, which slightly changes the behaviour in that Sonic additionally becomes immune during his partially-crouched state. My question - and I feel like this is something I should probably know if I have a green badge, but so what - is whether that saves any notable number of cycles in reality, particularly given the tradeoff that it changes the intended behaviour of the game? I would not normally choose such a tradeoff but I might be swayed if the optimisation is genuinely worthwhile.
It's entirely your choice which you pick. The off-frame only happens for a split second, and pretty much not noticeable. It DOES save a fair bit of time in reality. Reason why: Code (ASM): cmpi.b #9,anim(a0) ; is Sonic spindashing? beq.s Duckinganddashing ; if so, branch ;------------------------------------------------------------------------------- cmpi.b #$02, (A0) ; Is Miles? bne.s Touch_Check_Sonic ; Not goto Sonic routine cmpi.b #$5B, mapping_frame(A0) ; is Miles ducking bne.s Touch_NoDuck bra.s Duckinganddashing Touch_Check_Sonic: ;------------------------------------------------------------------------------- cmpi.b #$4D,mapping_frame(a0) ; is Sonic ducking? bne.s Touch_NoDuck ; if not, branch Duckinganddashing: ; So, Sonic is spindashing or ducking addi.w #$C,d3 moveq #$A,d5 ; loc_3F592: Touch_NoDuck: Imagine you're Sonic, and you hold the down button to crouch. Imagine Tails is following you, he copies your controls, so he's also crouching. Esrael's way: Sonic: It asks if you're spindashing, and then if you are, branch. As we're not, it continues. Are you Tails? Nope, let's branch. Is Sonic ducking? Yes, do not branch. Tails: It asks if you're spindashing, and then if you are, branch. As we're not, it continues. Are you Tails? Yes! Continue, is he ducking? Yes! So do not branch. Then branch to the ducking routine. This has got to be repeated for both Sonic and Tails every single frame. And that's touch_response only. It's also got to do this again for BOTH Sonic and Tails in the ring code! So, it's doing it 4 times in a frame. Then if you're in CNZ, for the bumpers, it's got to do it again for both of them, that's 6 times every frame! It's got to keep asking if you're Tails, and it's got to do more branches. My way: Code (ASM): cmpi.b #9,anim(a0) ; is Sonic spindashing? beq.s Duckinganddashing ; if so, branch cmpi.b #8,anim(a0) ; is Sonic ducking? bne.s Touch_NoDuck ; if not, branch Duckinganddashing: ; So, Sonic is spindashing or ducking addi.w #$C,d3 moveq #$A,d5 ; loc_3F592: Touch_NoDuck: Again, imagine you're Sonic, and you hold the down button to crouch. Imagine Tails is following you, he copies your controls, so he's also crouching. Sonic: It asks if you're spindashing, and then if you are, branch. As we're not, it continues. Are you ducking? Yes, do not branch and do the routine. Tails: Exactly the same. Basically, mine has saved it from asking if you're Tails all the time and stopping it from branching here and there. It may not look much, but seeming as it has to do this for BOTH Sonic and Tails every single frame, same with rings and if CNZ, the bumpers, my way will save it a fair few cycles. Seeming as Sonic is like this for only a split second, I think my way is better. In my hack, I've got it set to the coding I've shown. And I've never noticed any difference to what is was like before. But it all depends on preference. If you don't like this fact (or even knowing it), then Esrael's way is the way to go. But it just will take a little tiny bit longer. If going Esrael's way, the slowdown probably won't be noticeable unless near water or in it, or when you lose a lot of rings. EDIT: In fact, in S3K, this is completely gone from the game. It doesn't bother shortening his y_radius when ducking or spindashing. I guess they've done this to save cycles. And the other reason is because there isn't really any point you would "duck" to avoid anything. I tried placing the shooting arrow (from that head object in Marble Garden Zone) and tried avoiding it by ducking, and when it's about to miss you, it still hurts you. The checks isn't present in the touch_response, the rings collision or the boss (obviously no bumbers from CNZ).
Well, I will now go forth and backport these fixes into my hack. Esrael and RHS, you both have made you way into the Special Thanks section of the credits.
Cool, I know that means I've done well. Can I suggest something to any admin or staff? Can this topic be pinned? That way in the future, all members will see this and can spot these bug fixes and apply them, making further Sonic 2 hacks bug-ridden. Just a suggestion.
What I meant was that all future hacks will have got "rid" of all the bugs we've mentioned. Not all hacks in the future will be "ridden" with bugs =P
While testing and playing I have found a bug with Metal Sonic. He will fall forever since he can't detect the floor, because his initial animation use same id as Sonic and Miles while dying. To fix add the following lines to code: Code (ASM): ; loc_1E596: Floor_ChkTile: move.w d2,d0 .... movea.l d1,a1 ;-------------------------------------- cmpi.b #$06, $0024(A0) bne.s Player_Not_Death cmpi.b #$01, (A0) ; Is Sonic beq.s Player_Death ; cmpi.b #$02, (A0) ; Is Miles bne.s Player_Not_Death ; Player_Death: ; move.l #$FFFF0000, A1 Player_Not_Death: ;--------------------------------------- rts ; =========================================================================== ; precalculated values for Floor_ChkTile ; (Sonic 1 calculated it every time instead of using a table) word_1E5D0: The following explanation is for Sonic 2 rev 2. About Metal Sonic, there is a very well know bug in Sonic 2 rev 2 (see image). But there is another in rev 2 which is not noticed with Grabber enemy legs (see image) The following code is shared between Metal Sonic and Grabber enemy Code from Sonic 2 rev 1 Code (ASM): loc_367AA: move.b render_flags(a0),d0 andi.b #$FC,d0 move.b status(a0),d2 andi.b #$FC,d2 move.b render_flags(a1),d1 andi.b #3,d1 or.b d1,d0 or.b d1,d2 move.b d0,render_flags(a0) move.b d2,status(a0) rts Code from Sonic 2 rev 2 which cause Metal Sonic and Grabber enemy legs bug Code (ASM): Offset_0x0361D0: ; Usado pelo objeto 0xA7 - Grabber move.b $0001(A0), D0 andi.b #$FD, D0 ; <----------- #$FC in rev 1 move.b $0022(A0), D2 andi.b #$FD, D2 ; <----------- #$FC in rev 1 move.b $0001(A1), D1 andi.b #$02, D1 ; <----------- #$03 in rev 1 or.b D1, D0 or.b D1, D2 move.b D0, $0001(A0) move.b D2, $0022(A0) rts Why this code was changed??? Edit: 28/05/2019 - Fixed broken links Best regards: ---------------------- Neto.
@redhotsonic. I agree with Overlord. Pinning this defeats the purpose of a SCHG wiki in some respect. That being said... KingofHarts Page update! http://info.sonicret...Z_Tornado_death - I made a small error in the page title... I wanted it to say "Prevent SCZ Tornado spin dash death" If an admin, wiki sysop, or someone could fix that, would be good... or if its not a big deal, then leave it http://info.sonicret...ion_while_dying - Added the fix to allow Silver Sonic to land on the floor http://info.sonicret...r_collision_bug And about this... Isn't this to prevent Tails from fucking you over on the boss? I'm not against this fix, but if its to be performed, it should be more of a design choice, and while we are at it... should have some kind of guide that allows Tails to do other stuff... like break monitors, etc. I would think putting that all together into one guide would be sufficient.
From what I can tell, the bug mentioned only happens when Sonic (or Tails) is on the air and dies due to falling of the bottom of the screen; if I am wrong, please ignore me. This is the only case when there are physics checks (collision, movement) on the same frame as Sonic (or Tails dies) due to the location where it happens in code. So there is a neater fix that also does not cause the problem with Metal Sonic (and who knows how many other problems -- maybe with animals?). I will give the labels for the SVN disassembly, and the nearest 2007 label I can find. For Sonic, find this block of code: Code (ASM): Sonic_Boundary_Bottom: ;; bra.w JmpTo_KillCharacter ; =========================================================================== ; loc_1A9BA: and change it to this: Code (ASM): Sonic_Boundary_Bottom: ;; addq.l #4,sp bra.w JmpTo_KillCharacter ; =========================================================================== ; loc_1A9BA: For Tails, the relevant code block is this: Code (ASM): Tails_Boundary_Bottom: ;; bra.w JmpTo2_KillCharacter ; =========================================================================== ; loc_1C5A0: Do the same change as for Sonic. These changes will cause Sonic (and Tails) to skip some subroutines for the current control mode; this includes some that move Sonic (or Tails) and either make Sonic/Tails follow the ground or collide with the level. This will only happen during one frame; starting the next frame will work as normal since a different subroutine will be used. Being crushed by objects, drowning and being killed by badniks don't need to be changed because they all happen after the physics updates, and will only make effect on the next frame.
For Miles breaking Monitors do the following changes: Find and delete: Code (ASM): ; sub_12768: SolidObject_Monitor_Tails: btst d6,status(a0) bne.s loc_12782 tst.w (Two_player_mode).w ; <--- Comment or delete this line beq.w loc_199F0 ; <--- Comment or delete this line cmpi.b #2,anim(a1) bne.w loc_199F0 rts ; End of function SolidObject_Monitor_Tails ; --------------------------------------------------------------------------- as result Code (ASM): ; sub_12768: SolidObject_Monitor_Tails: btst d6,status(a0) bne.s loc_12782 cmpi.b #2,anim(a1) bne.w loc_199F0 rts ; End of function SolidObject_Monitor_Tails ; --------------------------------------------------------------------------- and find: Code (ASM): loc_3F768: cmpa.w #MainCharacter,a0 ; <--- Comment or delete this line beq.s + ; <--- Comment or delete this line tst.w (Two_player_mode).w ; <--- Comment or delete this line beq.s return_3F78A ; <--- Comment or delete this line + ; <--- Comment or delete this line cmpi.b #2,anim(a0) bne.s return_3F78A neg.w y_vel(a0) ; reverse Sonic's y-motion move.b #4,routine(a1) move.w a0,parent(a1) return_3F78A: rts as result Code (ASM): loc_3F768: cmpi.b #2,anim(a0) bne.s return_3F78A neg.w y_vel(a0) ; reverse Sonic's y-motion move.b #4,routine(a1) move.w a0,parent(a1) return_3F78A: rts This will allow Miles breaking monitors, but now Miles will be awarded with Monitor contents. If you don't want Miles getting monitors rewards you will need do some changes code as example Super Rings: Find: Code (ASM): super_ring: addq.w #1,(a2) lea (Ring_count).w,a2 lea (Update_HUD_rings).w,a3 lea (Extra_life_flags).w,a4 lea ($FFFFFEF0).w,a5 cmpa.w #MainCharacter,a1 beq.s loc_12992 lea (Ring_count_2P).w,a2 lea (Update_HUD_rings_2P).w,a3 lea (Extra_life_flags_2P).w,a4 lea ($FFFFFEF2).w,a5 loc_12992: and add the following lines Code (ASM): super_ring: addq.w #1,(a2) lea (Ring_count).w,a2 lea (Update_HUD_rings).w,a3 lea (Extra_life_flags).w,a4 lea ($FFFFFEF0).w,a5 cmpa.w #MainCharacter,a1 beq.s loc_12992 tst.w (Two_player_mode).w ; Add this line beq.s loc_12992 ; Add this line lea (Ring_count_2P).w,a2 lea (Update_HUD_rings_2P).w,a3 lea (Extra_life_flags_2P).w,a4 lea ($FFFFFEF2).w,a5 loc_12992: This will be necessary for all items which you want Main player to be rewarded.
That's true. Thought I'd suggest =P Anyway, another bug fix: How to fix the CPZ pipes bug So here's the demonstration of the glitch from another user on YouTube. This only happens when you've got hurt and land straight into the pipe's entrance. To be honest, this is very rare that you'll pull this bug off. But if you want to fix it anyway, it's extremely simple to. Go to "loc_225FC:" and look for these commands: Code (ASM): moveq #0,d3 cmpi.w #$A0,d2 beq.s + Just above the "moveq #0,d3", add this line: Code (ASM): move.b #2,routine(a1) ; In case character was hurt, make him okay again, fixes bug So, you end up with this: Code (ASM): loc_225FC: tst.w (Debug_placement_mode).w bne.w return_22718 move.w objoff_2A(a0),d2 move.w x_pos(a1),d0 sub.w x_pos(a0),d0 cmp.w d2,d0 bcc.w return_22718 move.w y_pos(a1),d1 sub.w y_pos(a0),d1 cmpi.w #$80,d1 bcc.w return_22718 cmpi.b #$20,anim(a1) beq.w return_22718 move.b #2,routine(a1) ; In case character was hurt, make him okay again, fixes bug moveq #0,d3 cmpi.w #$A0,d2 beq.s + moveq #8,d3 cmpi.w #$120,d2 beq.s + moveq #4,d3 neg.w d0 addi.w #$100,d0 + Done! You should now end up with this: Cheers, redhotsonic EDIT: Forgot to mention, this will also fix it for the sidekick.
I've had that one lying around for a while, too. Only difference is I put the fix here: Code (ASM): loc_22688: move.b d2,1(a4) add.w d3,d2 add.w d2,d2 andi.w #$1E,d2 lea off_22980(pc),a2 adda.w (a2,d2.w),a2 move.w (a2)+,4(a4) subq.w #4,4(a4) move.w (a2)+,d4 add.w x_pos(a0),d4 move.w d4,x_pos(a1) move.w (a2)+,d5 add.w y_pos(a0),d5 move.w d5,y_pos(a1) move.l a2,6(a4) move.w (a2)+,d4 add.w x_pos(a0),d4 move.w (a2)+,d5 add.w y_pos(a0),d5 addq.b #2,(a4) move.b #2,routine(a1) ; <--- move.b #$81,obj_control(a1) move.b #AniIDSonAni_Roll,anim(a1) move.w #$800,inertia(a1) But as far as I can tell, it doesn't make a difference. I'll contribute one: Fix Tails interacting with forced roll switchers while flying bug Most commonly seen in CNZ, when you lose Tails and he starts flying after you, sometimes he'll be stuck in an odd animation and when he lands will be in forced rolling mode. So, to fix this, first we go to Obj84_MainY (loc_212F6) and we'll see this: Code (ASM): ; loc_212F6: Obj84_MainY: tst.w (Debug_placement_mode).w bne.s return_21350 move.w y_pos(a0),d1 lea objoff_34(a0),a2 ; a2=object lea (MainCharacter).w,a1 ; a1=character bsr.s + lea (Sidekick).w,a1 ; a1=character + tst.b (a2)+ bne.s Obj84_MainY_Alt cmp.w y_pos(a1),d1 bhi.s return_21350 move.b #1,-1(a2) move.w x_pos(a0),d2 move.w d2,d3 move.w objoff_32(a0),d4 sub.w d4,d2 add.w d4,d3 move.w x_pos(a1),d4 cmp.w d2,d4 blo.s return_21350 cmp.w d3,d4 bhs.s return_21350 btst #0,render_flags(a0) bne.s + move.b #1,spindash_flag(a1) bra.w loc_212C4 ; --------------------------------------------------------------------------- + move.b #0,spindash_flag(a1) return_21350: rts Now, after the line Code (ASM): lea (Sidekick).w,a1 ; a1=character add this: Code (ASM): cmpi.w #4,(Tails_CPU_routine).w ; TailsCPU_Flying beq.s return_21350 which should leave us with this: Code (ASM): ; loc_212F6: Obj84_MainY: tst.w (Debug_placement_mode).w bne.s return_21350 move.w y_pos(a0),d1 lea objoff_34(a0),a2 ; a2=object lea (MainCharacter).w,a1 ; a1=character bsr.s + lea (Sidekick).w,a1 ; a1=character cmpi.w #4,(Tails_CPU_routine).w ; TailsCPU_Flying beq.s return_21350 + (...) Done. What we're doing here is simply skipping the collision check with the pinball mode switcher object for the second player if he's currently flying.