Knowing my luck, yes. The boss has been edited for the way he shoots more arrows. I tried fiddling with it, but no avail'. But if you're sure this fix definitely works, then it's a problem on my end and will look into it. Cheers, either way!
Some changes and fixes for Sonic 2
#137
Posted 25 August 2013 - 06:45 AM
Okay, flamewing. Your fix for the ARZ glitch definitely does NOT work. I even performed the glitch in your hack:



flamewing, I will send you a savestate which will perform this glitch via PM. I even tried your fix in the original S2 ROM. Still happens.
Anyway, your fix was along the right lines, but not in the right place. Reason why? Well, I tried doing this instead temporarily:
With this code, Eggman will NEVER use the hammer because the angle (routine) is always 2 or more. He will just stay in one spot forever and ever. Yet, I was still able to perform this glitch. So, your fix does not work.
The real fix
Now, I noticed that it usually happens just a moment before he stops moving left/right. So, using your fix as a guide, I tried this instead:
This code adds 2 to the angle (routine) just a split second before Eggman stops moving from side to side. Now I cannot get this glitch to happen. I had a savestate in my S2R game where this glitch would happened, applied this fix, and even using the savestate, the glitch will now NOT happen.
Hope this helps you and many others.



flamewing, I will send you a savestate which will perform this glitch via PM. I even tried your fix in the original S2 ROM. Still happens.
Anyway, your fix was along the right lines, but not in the right place. Reason why? Well, I tried doing this instead temporarily:
cmpi.b #$C0,mapping_frame(a0) bne.s loc_306F8 cmpi.b #2,angle(a0) bge.s loc_306F8
With this code, Eggman will NEVER use the hammer because the angle (routine) is always 2 or more. He will just stay in one spot forever and ever. Yet, I was still able to perform this glitch. So, your fix does not work.
The real fix
Now, I noticed that it usually happens just a moment before he stops moving left/right. So, using your fix as a guide, I tried this instead:
loc_3069E: cmpi.b #8,angle(a0) beq.s loc_306AA addq.b #2,angle(a0) move.w #0,($FFFFF758).w loc_306AA:
This code adds 2 to the angle (routine) just a split second before Eggman stops moving from side to side. Now I cannot get this glitch to happen. I had a savestate in my S2R game where this glitch would happened, applied this fix, and even using the savestate, the glitch will now NOT happen.
Hope this helps you and many others.
This post has been edited by redhotsonic: 25 August 2013 - 06:53 AM
#138
Posted 25 August 2013 - 08:27 AM
Actually -- and you should have seen this coming -- I manged to reproduce the glitch with your fix applied 
So:
The Really real fix for the ARZ boss
Use both fixes at the same time. Why? Well, there are two cases that cause the boss to blast-off: one when he is stopping moving left or right and one when he is just about to start swinging his hammer. RedHotSonic's fix applies to the first case, mine applies to the second case.
Now it is time to find out how many similar cases there are for Silver Sonic...
So:
The Really real fix for the ARZ boss
Use both fixes at the same time. Why? Well, there are two cases that cause the boss to blast-off: one when he is stopping moving left or right and one when he is just about to start swinging his hammer. RedHotSonic's fix applies to the first case, mine applies to the second case.
Now it is time to find out how many similar cases there are for Silver Sonic...
This post has been edited by flamewing: 25 August 2013 - 08:30 AM
#139
Posted 25 August 2013 - 08:48 AM
flamewing, on 25 August 2013 - 08:27 AM, said:
Use both fixes at the same time. Why? Well, there are two cases that cause the boss to blast-off: one when he is stopping moving left or right and one when he is just about to start swinging his hammer. RedHotSonic's fix applies to the first case, mine applies to the second case.
Ah, this boss is sneakier than we thought. Well, at least we can safely say it's now fixed =P
flamewing, on 25 August 2013 - 08:27 AM, said:
The Really real
lol!
EDIT: Got tags wrong on quote.
This post has been edited by redhotsonic: 25 August 2013 - 08:51 AM
#140
Posted 04 October 2013 - 09:58 PM
How to prevent level wraps in S1, S2 and S3&K
Every classic Sonic game has them: gather enough speed (or use zipping mechanisms, or debug mode), go through the left edge of the screen and bam -- you are now at the end of the level. This is how you can completely eliminate level wraps from your hack.
In all cases, I am assuming the Hg disassembly; it should be easy to port it over to your favorite outdated disassembly.
Sonic 1
Find the routine "Sonic_LevelBound" (it is in file "_incObj/Sonic LevelBound.asm"); it starts like this:
Change this routine so it looks like this:
You are done.
Sonic 2
Find the routine "Sonic_LevelBound"; it starts like this:
Change this routine so it looks like this:
Now find the routine "Tails_LevelBound" and do the same. From now on, no matter how much speed you gain, you can never go past the left boundary of the screen and do a level wrap.
Sonic 3 & Knuckles
Find the function "Player_Check_Screen_Boundaries"; it looks like this:
Now change it to look like this:
Now find the routine "Tails_Check_Screen_Boundaries" and do the same. You are done.
So, what is going on?
When computing the position to compare against the left boundary, if the speed is negative (I.e., to the left) and it is larger, in magnitude, than the current X position, applying the speed to the position causes the result to become negative, effectively becoming a large positive number. When compared to the minimum camera X + 10, it is considered a valid value. The additional code checks for this underflow in the position, and prevents it from happening.
Every classic Sonic game has them: gather enough speed (or use zipping mechanisms, or debug mode), go through the left edge of the screen and bam -- you are now at the end of the level. This is how you can completely eliminate level wraps from your hack.
In all cases, I am assuming the Hg disassembly; it should be easy to port it over to your favorite outdated disassembly.
Sonic 1
Find the routine "Sonic_LevelBound" (it is in file "_incObj/Sonic LevelBound.asm"); it starts like this:
Sonic_LevelBound: ; XREF: Obj01_MdNormal; et al move.l obX(a0),d1 move.w obVelX(a0),d0 ext.l d0 asl.l #8,d0 add.l d0,d1 swap d1 move.w (v_limitleft2).w,d0 addi.w #$10,d0 cmp.w d1,d0 ; has Sonic touched the side boundary? bhi.s @sides ; if yes, branch
Change this routine so it looks like this:
Sonic_LevelBound: ; XREF: Obj01_MdNormal; et al moveq #0,d2 move.l obX(a0),d1 smi.b d2 ; Set d2 if player on position > 32767 add.w d2,d2 ; Move bit up move.w obVelX(a0),d0 spl.b d2 ; Set if speed is positive add.w d2,d2 ; Move bit up ext.l d0 asl.l #8,d0 add.l d0,d1 spl.b d2 ; Set if position+speed is < 32768 move.w (v_limitleft2).w,d0 addi.w #$10,d0 tst.w d2 ; If d2 is zero, we had an underflow of position beq.s @sides swap d1 cmp.w d1,d0 ; has Sonic touched the side boundary? bhi.s @sides ; if yes, branch
You are done.
Sonic 2
Find the routine "Sonic_LevelBound"; it starts like this:
; loc_1A974: Sonic_LevelBound: move.l x_pos(a0),d1 move.w x_vel(a0),d0 ext.l d0 asl.l #8,d0 add.l d0,d1 swap d1 move.w (Camera_Min_X_pos).w,d0 addi.w #$10,d0 cmp.w d1,d0 ; has Sonic touched the left boundary? bhi.s Sonic_Boundary_Sides ; if yes, branch
Change this routine so it looks like this:
; loc_1A974: Sonic_LevelBound: moveq #0,d2 move.l x_pos(a0),d1 smi.b d2 ; Set d2 if player on position > 32767 add.w d2,d2 ; Move bit up move.w x_vel(a0),d0 spl.b d2 ; Set if speed is positive add.w d2,d2 ; Move bit up ext.l d0 asl.l #8,d0 add.l d0,d1 spl.b d2 ; Set if position+speed is < 32768 move.w (Camera_Min_X_pos).w,d0 addi.w #$10,d0 tst.w d2 ; If d2 is zero, we had an underflow of position beq.s Sonic_Boundary_Sides swap d1 cmp.w d1,d0 ; has player touched the left boundary? bhi.s Sonic_Boundary_Sides ; if yes, branch
Now find the routine "Tails_LevelBound" and do the same. From now on, no matter how much speed you gain, you can never go past the left boundary of the screen and do a level wrap.
Sonic 3 & Knuckles
Find the function "Player_Check_Screen_Boundaries"; it looks like this:
Player_Check_Screen_Boundaries: move.l $10(a0),d1 move.w $18(a0),d0 ext.l d0 asl.l #8,d0 add.l d0,d1 swap d1 move.w (Camera_min_X_pos).w,d0 addi.w #$10,d0 cmp.w d1,d0 bhi.s loc_11732
Now change it to look like this:
Player_Check_Screen_Boundaries: moveq #0,d2 move.l $10(a0),d1 smi.b d2 ; Set d2 if player on position > 32767 add.w d2,d2 ; Move bit up move.w $18(a0),d0 spl.b d2 ; Set if speed is positive add.w d2,d2 ; Move bit up ext.l d0 asl.l #8,d0 add.l d0,d1 spl.b d2 ; Set if position+speed is < 32768 move.w (Camera_min_X_pos).w,d0 addi.w #$10,d0 tst.w d2 ; If d2 is zero, we had an underflow of position beq.s loc_11732 swap d1 cmp.w d1,d0 bhi.s loc_11732
Now find the routine "Tails_Check_Screen_Boundaries" and do the same. You are done.
So, what is going on?
When computing the position to compare against the left boundary, if the speed is negative (I.e., to the left) and it is larger, in magnitude, than the current X position, applying the speed to the position causes the result to become negative, effectively becoming a large positive number. When compared to the minimum camera X + 10, it is considered a valid value. The additional code checks for this underflow in the position, and prevents it from happening.
This post has been edited by flamewing: 04 October 2013 - 10:28 PM
#141
Posted 05 December 2014 - 11:17 AM
CNZ's bumpers are prone to very well hidden bug, which will trigger if you move your data around a lot or try optimising the code near SpecialCNZBumpers_Act1. The bug is that the large bumpers no longer bounce Sonic or Tails off of them. There doesn't seems to be any collision-related effects at all: no sound, nothing. I personally found this bug when I changed the nearby 'jmp (PlaySound).l' to a 'jmp (PlaySound).w'. Boy, was I surprised to find that was the cause of my problem!
The bumpers' layout files contain entries that are 6 bytes in size. Two dummy entries are needed for the bumper manager to function properly: one at the beginning, and one at the end. I believe the first dummy needs an X-pos of $0000, while the last one needs $FFFF. Now, CNZ act 2's bumpers file starts and ends with dummy entries, but act 1... it doesn't start with one. In fact, the jmp right before the binclude just happens to have $0000 in the same place as an entry's X-pos (jmp $0000XXXX), so it works. This could have been a real goofy space optimisation by Sonic Team.
To fix this, you just gotta shove 6 blank bytes in the beginning of the CNZ act 1 bumper layout file. Tada. However, there is a 'better' way. By exploiting the bumper manager's logic, you can shave some bytes off:
First off, remove the first two bytes of your new blank dummy entry at the beginning of your file. Then, find the pointer to SpecialCNZBumpers_Act1, and just append a '-2' to the end of the address. The first byte of information is unneeded as only the X-pos is of any use to dummy entries. Next, the dummy entry at the end of the file can also be trimmed. It should be '0000FFFF0000'. You can remove the last two bytes. Again, we only need the X-pos. You can also apply this to act 2's file.
The bumpers' layout files contain entries that are 6 bytes in size. Two dummy entries are needed for the bumper manager to function properly: one at the beginning, and one at the end. I believe the first dummy needs an X-pos of $0000, while the last one needs $FFFF. Now, CNZ act 2's bumpers file starts and ends with dummy entries, but act 1... it doesn't start with one. In fact, the jmp right before the binclude just happens to have $0000 in the same place as an entry's X-pos (jmp $0000XXXX), so it works. This could have been a real goofy space optimisation by Sonic Team.
To fix this, you just gotta shove 6 blank bytes in the beginning of the CNZ act 1 bumper layout file. Tada. However, there is a 'better' way. By exploiting the bumper manager's logic, you can shave some bytes off:
First off, remove the first two bytes of your new blank dummy entry at the beginning of your file. Then, find the pointer to SpecialCNZBumpers_Act1, and just append a '-2' to the end of the address. The first byte of information is unneeded as only the X-pos is of any use to dummy entries. Next, the dummy entry at the end of the file can also be trimmed. It should be '0000FFFF0000'. You can remove the last two bytes. Again, we only need the X-pos. You can also apply this to act 2's file.
This post has been edited by Clownacy: 05 December 2014 - 02:06 PM
#142
Posted 28 April 2015 - 12:19 PM
I haven't provided any fixes for a while; mainly due to the fact I hardly hack at all these days, you know, with real life getting in the way. Anyway, I was playing Sonic 2 the other day and realised a fair few issues with the MCZ boss. You may consider these bugs, you may not, but to me, they're not right.
So there's at least 5 bugs; 7 if you want to make the design changes. Let's get coding! I'm using Xenowhirl's disassembly as a guide.
Step 1 - Making the "stop-and-drill" routine occur every time Sonic and Tails are hurt

Eggman finding it funny when Tails is hit

Not so much when Sonic is hurt though
Go to "loc_3124A:" and you'll see this:
See the "tst.b objoff_38(a0)" bit? From there, delete it all. So now you have a gap between "bpl.w loc_312E8" and "loc_31274:". The code you just deleted, we're going to replace with this:
So you'll end up with this:
Now, Eggman will enter his "stop-and-drill" routine every time Sonic and Tails have been hit. Yet, he won't laugh at all anymore. That's the next bit.
Step 2 - Make Eggman laugh every time Sonic or Tails has been hit

Suddenly Eggman isn't in a laughing mood
Go to "loc_31298:"
This bit of coding is no longer being used after what we just did in Step 1. Good, this is in a bad place really. If we left the code we changed to branch here, Eggman will indeed laugh when Sonic and Tails have been hit, but only when he changes into his "stop-and-drill routine". Meaning, if you get hit when he has stopped, or when he is about to drill, or is coming down from drilling, whatever, he still will not laugh.
Anyway, delete the two lines under the label "loc_31298:". We're moving it. Because the label no longer exists, directly above is a branch to the label to what used to be underneath. This is illegal (most assemblers will create a "nop" to avoid this but still). So under "loc_31288:", delete this line:
So, you'll end up with this:
Next, go to "loc_31470:" and directly below this label, insert this code:
So you'll end up with this:
Now, every time you're hurt, at any point during the boss, Eggman will laugh, like he is meant to! The reason why we check to see if Eggman is already laughing is because when set, a countdown gets set and counts down 1 every frame. But as soon as it goes down by 1, without the check, it'll set the counter back to 30 and it'll do this for every frame until you fall on the floor. Because of this, Eggman will display the laughing face but won't actually animate, because the counter is stuck on 30. Doing this check will set it to 30, but then it will let it countdown like it is meant to, making his laugh animate.
That's the first 3 bugs fixed already after 2 steps!

Eggman now a bit happier Sonic is hurt and decides to stop and prepare his drills

Eggman really is happier now
Step 3 - Stop the screen shaking when dead
When you die in this boss, like all other bosses and when in normal levels, nearly everything comes to a standstill. In this boss, rings, Eggman, and the falling rocks comes to a standstill. Yet, if you die when the screen was shaking, it will continue to shake. It looks awfully weird that the screen continues to shake yet the falling rocks have stopped mid-air. Let's fix this.
Go to "loc_CD54:" (which is nothing to do with the MCZ boss code, but with MCZ layer deformation), and after where you see:
Insert this:
So you end up with this:
This will stop the screen shaking when you die if it was already shaking. BUT WAIT, the screen shaking noise is still present, let's stop that.
Go to "LevEvents_MCZ2_Routine4:" (which is nothing to do with the layer deformation code, but with MCZ's level events), after:
Again, insert this:
So you end up with this:
This will stop the noise happening when you die.
Step 4 - Disable Eggman from turning and facing Sonic when on the side of the screen

Eggman locates Sonic, but he won't do too much
You can argue this isn't a bug, but I believe it is. Eggman spawns on the left side of the screen facing right. If you're to the left of him (hugging the left screen), he will turn and try to move, then pretty much go into his "stop-and-drill" routine pretty quickly because he doesn't move anywhere (this happens even without the first 3 bugs we've just fixed). Eggman is on the left and is facing right, let him go right. This happens on the other side of the screen too (As seen in the picture). Luckily, the fix is very simple!
Go to "loc_311AA:". After the "move.b #$30,1(a1)" line, insert this:
When Eggman comes down at the beginning of the boss fight, he spawns in the middle; #$21A0 being his X co-ordinate. So what it is doing here, is if Eggman is at this position, then do NOT branch and aim for Sonic.
The rest of the time when he comes down, he'll be at the left or right of the screen. So, he won't be in this X co-ordinate anymore. Therefore, he will no longer aim for Sonic. So, if he spawns on the left, he will be facing right, and he'll go right!

That's more like it
Step 5 - Make Eggman actually start in the middle of the screen (optional)

No, not quite centre
This is more of a design choice, but could be considered a bug. I just find it weird that he spawns just too little to the right of the centre of the screen. Anyway, simple fix if you want him dead centre. Go to "loc_30FB8:" and 4th line down, change:
to this:
He'll now start in the centre instead. BUT WAIT! Did you follow step 4? If so, step 4 will no longer work, so go back to "loc_311AA:" and change:
to this:
And step 4 won't need to be re-done.

Eggman likes to be precise with his entrance
Step 6 - Make Eggman at the beginning aim for Tails too (optional)
Again, design choice. When Eggman comes down at the beginning, he faces and aims for Sonic. Completely ignores Tails. Strange that at first he only used to laugh when he hit Tails and not care about Sonic. What we're going to do here is when Eggman comes down, whoever is closest, he will aim and go for!
At "loc_311AA:" and after "bclr #0,render_flags(a0)" you'll see this code:
Delete it. And replace it with this:
So, you'll end up with this:
Eggman will now aim for whoever is closer out of Sonic and Tails. Because you followed step 4, this will only do it when the boss starts (unless you didn't do step 5, and if you didn't, make sure you change the:
back to it's normal:
so this step takes effect).

Tails is a lot closer, think Eggman will go for him instead
Step 7 - Quick branch fix
Chances are your disassembly will come with an out-of-reach error. At "loc_311AA:", change:
to:
All done. That's all bugs fixed!
- Eggman will stop moving sideways on the floor when he hurts Tails, then goes back up into the ground (stop-and-drill routine), yet he won't do any of this when he hits Sonic.
- Unless he hits Tails to go into the stop-and-drill routine, Eggman will not laugh when he hits Sonic OR Tails.
- If Sonic alone or Tails alone, Eggman won't laugh or enter the stop-and-drill routine at all.
- When Eggman comes to the floor, he turns and aims for Sonic every time. This is fine the first time round when the boss starts as he starts in the middle, but the rest of the time he spawns on the sides; you don't want him turning ideally.
- Screen still shakes when you're dead, a bit weird since everything else like the falling rocks have come to a standstill.
- MCZ boss doesn't actually start in the middle of the screen (design choice more than a bug).
- When Eggman comes to the floor when he first starts, he turns and aims for Sonic but never for Tails (again, more of a design change than a bug).
So there's at least 5 bugs; 7 if you want to make the design changes. Let's get coding! I'm using Xenowhirl's disassembly as a guide.
Spoiler
Step 1 - Making the "stop-and-drill" routine occur every time Sonic and Tails are hurt

Eggman finding it funny when Tails is hit

Not so much when Sonic is hurt though
Go to "loc_3124A:" and you'll see this:
loc_3124A: subi.w #1,($FFFFF75C).w cmpi.w #$28,($FFFFF75C).w bgt.w loc_312E8 move.b #1,($FFFFF73F).w tst.w ($FFFFF75C).w bpl.w loc_312E8 tst.b objoff_38(a0) beq.s loc_31274 sf objoff_38(a0) bra.s loc_31298
See the "tst.b objoff_38(a0)" bit? From there, delete it all. So now you have a gap between "bpl.w loc_312E8" and "loc_31274:". The code you just deleted, we're going to replace with this:
cmpi.b #4,(MainCharacter+routine).w ; Did Sonic (or Sonic alone or Tails alone) get hit? bge.s + ; If so, branch cmpi.b #4,(Sidekick+routine).w ; Did Tails (Sidekick) get hit? blt.s loc_31274 ; If not, branch away + sf objoff_38(a0) ; Set the stop-and-drill routine bra.s loc_312A2 ; And branch to take effect
So you'll end up with this:
loc_3124A: subi.w #1,($FFFFF75C).w cmpi.w #$28,($FFFFF75C).w bgt.w loc_312E8 move.b #1,($FFFFF73F).w tst.w ($FFFFF75C).w bpl.w loc_312E8 cmpi.b #4,(MainCharacter+routine).w ; Did Sonic (or Sonic alone or Tails alone) get hit? bge.s + ; If so, branch cmpi.b #4,(Sidekick+routine).w ; Did Tails (Sidekick) get hit? blt.s loc_31274 ; If not, branch away + sf objoff_38(a0) ; Set the stop-and-drill routine bra.s loc_312A2 ; And branch to take effect ; =========================================================================== loc_31274:
Now, Eggman will enter his "stop-and-drill" routine every time Sonic and Tails have been hit. Yet, he won't laugh at all anymore. That's the next bit.
Step 2 - Make Eggman laugh every time Sonic or Tails has been hit

Suddenly Eggman isn't in a laughing mood
Go to "loc_31298:"
loc_31298: lea ($FFFFF740).w,a1 move.b #$30,7(a1)
This bit of coding is no longer being used after what we just did in Step 1. Good, this is in a bad place really. If we left the code we changed to branch here, Eggman will indeed laugh when Sonic and Tails have been hit, but only when he changes into his "stop-and-drill routine". Meaning, if you get hit when he has stopped, or when he is about to drill, or is coming down from drilling, whatever, he still will not laugh.
Anyway, delete the two lines under the label "loc_31298:". We're moving it. Because the label no longer exists, directly above is a branch to the label to what used to be underneath. This is illegal (most assemblers will create a "nop" to avoid this but still). So under "loc_31288:", delete this line:
bra.s loc_312A2
So, you'll end up with this:
loc_31288: cmpi.w #$2200,($FFFFF750).w blt.s loc_312E8 move.w #$2200,($FFFFF750).w ; =========================================================================== loc_312A2: move.w #0,($FFFFF758).w move.b #0,angle(a0) lea ($FFFFF740).w,a1 andi.b #$F0,2(a1) ori.b #$B,2(a1) andi.b #$F0,8(a1) ori.b #$B,8(a1) move.b #0,1(a1) andi.b #$F0,6(a1) ori.b #$D,6(a1) move.w #$64,($FFFFF75C).w move.w #-$C0,($FFFFF75A).w
Next, go to "loc_31470:" and directly below this label, insert this code:
cmpi.b #4,(MainCharacter+routine).w ; Did Sonic (or Sonic alone or Tails alone) get hit? bge.s + ; If so, branch cmpi.b #4,(Sidekick+routine).w ; Did Tails (Sidekick) get hit? blt.s ++ ; If not, branch away + lea ($FFFFF740).w,a1 ; Load Eggman's face animation into a1 cmpi.b #$30,7(a1) ; Is Eggman laughing already? bgt.s + ; If so, branch, and do not reset move.b #$30,7(a1) ; Start Eggman's laughing animation +
So you'll end up with this:
loc_31470: cmpi.b #4,(MainCharacter+routine).w ; Did Sonic (or Sonic alone or Tails alone) get hit? bge.s + ; If so, branch cmpi.b #4,(Sidekick+routine).w ; Did Tails (Sidekick) get hit? blt.s ++ ; If not, branch away + lea ($FFFFF740).w,a1 ; Load Eggman's face animation into a1 cmpi.b #$30,7(a1) ; Is Eggman laughing already? bgt.s + ; If so, branch, and do not reset move.b #$30,7(a1) ; Start Eggman's laughing animation + cmpi.b #8,angle(a0) bcc.s return_314B6 tst.b objoff_32(a0) beq.s loc_314B8 tst.b collision_flags(a0) bne.s return_314B6 tst.b objoff_14(a0) bne.s loc_3149A move.b #$20,objoff_14(a0) move.w #$AC,d0 jsr (PlaySound).l
Now, every time you're hurt, at any point during the boss, Eggman will laugh, like he is meant to! The reason why we check to see if Eggman is already laughing is because when set, a countdown gets set and counts down 1 every frame. But as soon as it goes down by 1, without the check, it'll set the counter back to 30 and it'll do this for every frame until you fall on the floor. Because of this, Eggman will display the laughing face but won't actually animate, because the counter is stuck on 30. Doing this check will set it to 30, but then it will let it countdown like it is meant to, making his laugh animate.
That's the first 3 bugs fixed already after 2 steps!

Eggman now a bit happier Sonic is hurt and decides to stop and prepare his drills

Eggman really is happier now
Step 3 - Stop the screen shaking when dead
When you die in this boss, like all other bosses and when in normal levels, nearly everything comes to a standstill. In this boss, rings, Eggman, and the falling rocks comes to a standstill. Yet, if you die when the screen was shaking, it will continue to shake. It looks awfully weird that the screen continues to shake yet the falling rocks have stopped mid-air. Let's fix this.
Go to "loc_CD54:" (which is nothing to do with the MCZ boss code, but with MCZ layer deformation), and after where you see:
loc_CD54: swap d0 moveq #6,d6 bsr.w loc_D940 move.w ($FFFFEE0C).w,($FFFFF618).w moveq #0,d2 tst.b ($FFFFEEBD).w beq.s +
Insert this:
lea (MainCharacter).w,a1 ; Load the Main Character into a1 cmpi.b #6,routine(a1) ; is the Main Character dead? bcc.s + ; if so, branch and skip shaking
So you end up with this:
loc_CD54: swap d0 moveq #6,d6 bsr.w loc_D940 move.w ($FFFFEE0C).w,($FFFFF618).w moveq #0,d2 tst.b ($FFFFEEBD).w beq.s + lea (MainCharacter).w,a1 ; Load the Main Character into a1 cmpi.b #6,routine(a1) ; is the Main Character dead? bcc.s + ; if so, branch and skip shaking move.w (Timer_frames).w,d0 andi.w #$3F,d0 lea SwScrl_RippleData(pc),a1 lea (a1,d0.w),a1 moveq #0,d0 move.b (a1)+,d0 add.w d0,(Vscroll_Factor).w add.w d0,($FFFFF618).w add.w d0,($FFFFEEF4).w move.b (a1)+,d2 add.w d2,($FFFFEEF0).w +
This will stop the screen shaking when you die if it was already shaking. BUT WAIT, the screen shaking noise is still present, let's stop that.
Go to "LevEvents_MCZ2_Routine4:" (which is nothing to do with the layer deformation code, but with MCZ's level events), after:
LevEvents_MCZ2_Routine4: tst.b ($FFFFEEBD).w beq.s +
Again, insert this:
lea (MainCharacter).w,a1 ; Load the Main Character into a1 cmpi.b #6,routine(a1) ; is the Main Character dead? bcc.s + ; if so, branch and skip shaking noise
So you end up with this:
LevEvents_MCZ2_Routine4: tst.b ($FFFFEEBD).w beq.s + cmpi.b #6,(MainCharacter+routine).w ; is Sonic dead? bcc.s + ; if so, branch and skip shaking noise move.w (Timer_frames).w,d0 andi.w #$1F,d0 bne.s + move.w #$E1,d0 bsr.w JmpTo3_PlaySound +
This will stop the noise happening when you die.
Step 4 - Disable Eggman from turning and facing Sonic when on the side of the screen

Eggman locates Sonic, but he won't do too much
You can argue this isn't a bug, but I believe it is. Eggman spawns on the left side of the screen facing right. If you're to the left of him (hugging the left screen), he will turn and try to move, then pretty much go into his "stop-and-drill" routine pretty quickly because he doesn't move anywhere (this happens even without the first 3 bugs we've just fixed). Eggman is on the left and is facing right, let him go right. This happens on the other side of the screen too (As seen in the picture). Luckily, the fix is very simple!
Go to "loc_311AA:". After the "move.b #$30,1(a1)" line, insert this:
cmpi.w #$21A0,($FFFFF750).w ; Only aim for Sonic at the beginning (so he doesn't turn on the side of the screen) bne.s loc_31210 ; First time coming down? Ah, aim then
When Eggman comes down at the beginning of the boss fight, he spawns in the middle; #$21A0 being his X co-ordinate. So what it is doing here, is if Eggman is at this position, then do NOT branch and aim for Sonic.
The rest of the time when he comes down, he'll be at the left or right of the screen. So, he won't be in this X co-ordinate anymore. Therefore, he will no longer aim for Sonic. So, if he spawns on the left, he will be facing right, and he'll go right!

That's more like it
Step 5 - Make Eggman actually start in the middle of the screen (optional)

No, not quite centre
This is more of a design choice, but could be considered a bug. I just find it weird that he spawns just too little to the right of the centre of the screen. Anyway, simple fix if you want him dead centre. Go to "loc_30FB8:" and 4th line down, change:
move.w #$21A0,x_pos(a0)
to this:
move.w #$2190,x_pos(a0) ; Make Eggman start dead-centre of the screen
He'll now start in the centre instead. BUT WAIT! Did you follow step 4? If so, step 4 will no longer work, so go back to "loc_311AA:" and change:
cmpi.w #$21A0,($FFFFF750).w ; Only aim for Sonic at the beginning (so he doesn't turn on the side of the screen)
to this:
cmpi.w #$2190,($FFFFF750).w ; Only aim for Sonic at the beginning (so he doesn't turn on the side of the screen)
And step 4 won't need to be re-done.

Eggman likes to be precise with his entrance
Step 6 - Make Eggman at the beginning aim for Tails too (optional)
Again, design choice. When Eggman comes down at the beginning, he faces and aims for Sonic. Completely ignores Tails. Strange that at first he only used to laugh when he hit Tails and not care about Sonic. What we're going to do here is when Eggman comes down, whoever is closest, he will aim and go for!
At "loc_311AA:" and after "bclr #0,render_flags(a0)" you'll see this code:
move.w (MainCharacter+x_pos).w,d0 sub.w ($FFFFF750).w,d0 bmi.s loc_31210 bset #0,render_flags(a0)
Delete it. And replace it with this:
; Check who is closer out of Sonic or Tails move.w (MainCharacter+x_pos).w,d0 ; Move Sonic's x_pos into d0 move.w (Sidekick+x_pos).w,d1 ; Move Tails's x_pos into d1 move.w ($FFFFF750).w,d2 ; Move Eggman's x_pos into d2 move.w d2,d3 ; Move Eggman's x_pos into d3 sub.w d0,d2 ; Subtract Sonic's x_pos from Eggman's bpl.s + ; If result is a positive, branch neg.w d2 ; As the result is a negative, negate it to positive + sub.w d1,d3 ; Subtract Tails's x_pos from Eggman's bpl.s + ; If result is a positive, branch neg.w d3 ; As the result is a negative, negate it to positive + cmp.w d2,d3 ; Is Sonic Closer? bgt.s + ; If so, branch ; Tails is closer cmpi.b #6,(Maincharacter+routine).w ; dead? bge.s + ; As Tails is dead, ignore Tails and aim for Sonic sub.w ($FFFFF750).w,d1 bmi.s loc_31210 bset #0,render_flags(a0) bra.s loc_31210 + ; Sonic is closer sub.w ($FFFFF750).w,d0 bmi.s loc_31210 bset #0,render_flags(a0)
So, you'll end up with this:
loc_311AA: bsr.w loc_2D5DE cmpi.w #$660,($FFFFF754).w blt.s loc_31228 move.w #$660,($FFFFF754).w addq.b #2,angle(a0) lea ($FFFFF740).w,a1 andi.b #$F0,2(a1) ori.b #6,2(a1) andi.b #$F0,8(a1) ori.b #6,8(a1) andi.b #$F0,6(a1) ori.b #$D,6(a1) move.b #$20,5(a1) move.w #$64,($FFFFF75C).w move.b #$30,1(a1) cmpi.w #$2190,($FFFFF750).w ; Only aim for Sonic at the beginning (so he doesn't turn on the side of the screen) bne.s loc_31210 ; First time coming down? Ah, aim then bclr #0,render_flags(a0) ; Check who is closer out of Sonic or Tails move.w (MainCharacter+x_pos).w,d0 ; Move Sonic's x_pos into d0 move.w (Sidekick+x_pos).w,d1 ; Move Tails's x_pos into d1 move.w ($FFFFF750).w,d2 ; Move Eggman's x_pos into d2 move.w d2,d3 ; Move Eggman's x_pos into d3 sub.w d0,d2 ; Subtract Sonic's x_pos from Eggman's bpl.s + ; If result is a positive, branch neg.w d2 ; As the result is a negative, negate it to positive + sub.w d1,d3 ; Subtract Tails's x_pos from Eggman's bpl.s + ; If result is a positive, branch neg.w d3 ; As the result is a negative, negate it to positive + cmp.w d2,d3 ; Is Sonic Closer? bgt.s + ; If so, branch ; Tails is closer cmpi.b #6,(Maincharacter+routine).w ; dead? bge.s + ; As Tails is dead, ignore Tails and aim for Sonic sub.w ($FFFFF750).w,d1 bmi.s loc_31210 bset #0,render_flags(a0) bra.s loc_31210 + ; Sonic is closer sub.w ($FFFFF750).w,d0 bmi.s loc_31210 bset #0,render_flags(a0) loc_31210: move.w #-$200,($FFFFF758).w move.w #0,($FFFFF75A).w btst #0,render_flags(a0) beq.s loc_31228 neg.w ($FFFFF758).w
Eggman will now aim for whoever is closer out of Sonic and Tails. Because you followed step 4, this will only do it when the boss starts (unless you didn't do step 5, and if you didn't, make sure you change the:
cmpi.w #$2190,($FFFFF750).w ; Only aim for Sonic at the beginning (so he doesn't turn on the side of the screen)
back to it's normal:
cmpi.w #$21A0,($FFFFF750).w ; Only aim for Sonic at the beginning (so he doesn't turn on the side of the screen)
so this step takes effect).

Tails is a lot closer, think Eggman will go for him instead
Step 7 - Quick branch fix
Chances are your disassembly will come with an out-of-reach error. At "loc_311AA:", change:
blt.s loc_31228
to:
blt.w loc_31228
All done. That's all bugs fixed!
#143
Posted 28 April 2015 - 01:07 PM
This is some pretty cool stuff... that said the only one I take issue with is having him always face the opposite side he comes down on when he's at the end of the screen. You basically made him go into empty space like a total derp. Outside of that, excellent stuff. Great to see you back RHS.
#144
Posted 28 April 2015 - 02:40 PM
How do you mean? Where have I made him come down in an empty space? Except from making him start dead centre at the beginning only, the rest of his "coming down" places haven't changed. In the normal S2(even after these fixes), if you're closer to the right side, Eggman will spawn on the left and face right, ready to come at you. Vice versa if you're at the left (if this is what you mean?).
This post has been edited by redhotsonic: 28 April 2015 - 02:41 PM
#145
Posted 11 July 2015 - 08:02 PM
(Ripped largely from ReadySonic)
Ever get snared in a bridge while in debug mode? Obviously, those things don't make any attempt to avoid interacting with the player while in debug mode, while many other objects do.
First up, let's fix up the debug object itself: go to Debug_Init and, below the 'move.b #AniIDSonAni_Walk,anim(a0)', add this:
Since Sonic and certain objects keep track of if they're being touched, and what by, we need to clear all that when entering debug mode. Without this additional fix, our fix would cause another bug where bridges stay deformed when entering debug mode.
Next up, the bridge itself. sub_F872 is what handles deforming the bridge, and changing the player's Y position accordingly. Since AI Tails doesn't enter debug mode with the player, we don't want to ignore the entire subroutine; only the part involving the main character.
Above 'lea (MainCharacter).w,a1', add this check:
Now we need to mess with those annoying nameless labels. Add a '+' before the 'rts', and change the 'blo.s ++' to 'blo.s +++'.
Ever get snared in a bridge while in debug mode? Obviously, those things don't make any attempt to avoid interacting with the player while in debug mode, while many other objects do.
First up, let's fix up the debug object itself: go to Debug_Init and, below the 'move.b #AniIDSonAni_Walk,anim(a0)', add this:
btst #3,status(a0) ; is Sonic standing on an object? beq.s + ; if not, branch bclr #3,status(a0) ; clear Sonic's standing flag move.b interact(a0),d0 ; get object ID clr.b interact(a0) ; clear object ID lsl.w #6,d0 addi.w #Object_RAM,d0 movea.w d0,a2 bclr #3,status(a2) ; clear object's standing flag +
Since Sonic and certain objects keep track of if they're being touched, and what by, we need to clear all that when entering debug mode. Without this additional fix, our fix would cause another bug where bridges stay deformed when entering debug mode.
Next up, the bridge itself. sub_F872 is what handles deforming the bridge, and changing the player's Y position accordingly. Since AI Tails doesn't enter debug mode with the player, we don't want to ignore the entire subroutine; only the part involving the main character.
Above 'lea (MainCharacter).w,a1', add this check:
tst.w (Debug_placement_mode).w bne.s +++
Now we need to mess with those annoying nameless labels. Add a '+' before the 'rts', and change the 'blo.s ++' to 'blo.s +++'.
This post has been edited by Clownacy: 14 July 2015 - 03:31 PM
#146
Posted 14 July 2015 - 11:23 AM
Xenowhirl conversion powers activate!
For the above: Go to Debug_Main and under this line in loc_41AAE:
Paste this:
Now just add a + before the rts and you're done. =)
For the above: Go to Debug_Main and under this line in loc_41AAE:
move.b #0,anim(a0)
Paste this:
btst #3,status(a0) ; is Sonic standing on an object? beq.s + ; if not, branch bclr #3,status(a0) ; clear Sonic's standing flag move.b interact(a0),d0 ; get object ID clr.b interact(a0) ; clear object ID lsl.w #6,d0 addi.w #Object_RAM,d0 movea.w d0,a2 bclr #3,status(a2) ; clear object's standing flag +And above:
lea (MainCharacter).w,a1 ; a1=character subq.b #1,d6 moveq #$3F,d5 +Paste this:
tst.w (Debug_placement_mode).w bne.s ++
Now just add a + before the rts and you're done. =)
This post has been edited by ThomasSpeedrunner: 14 July 2015 - 11:32 AM

00