INDEX - For Tails' tails invulnerable time glitch, read this post - For Tails' tails pushing animation error, click here for post - For Tails' tails balancing animation addition, click here for post - For Tails' tails looking up speed animation glitch, click here for post - For Tails' tails priority error glitch (EHZ boss's wheels as example), click here for post For Tails' tails invulnerable time glitch Here's a quick one for you lot. This isn't a bug as such, more like... a design change. We all know that Tails has another object attached to him half the time; "Tails' Tails". Used for when he's standing, jumping, etc. Sometimes, his tails are drawn within Tails himself, like when he is walking. Something that has always bugged me in Sonic 2 is that when he gets hurt, he becomes invulnerable for a couple of seconds, and he flashes, but the object "Tails' tails" does not. When this object isn't being used (like when Tails is walking and the tails are drawn within him) his tails do flash. To me, this looks strange. This happens in both Sonic 2 and Sonic 3 and Knuckles. I'm about to show you how to fix it in both games. Sonic 2 fix - Xenowhirl and SVN Disassemblies Go to "loc_1D288:" and you should see this: Code (ASM): loc_1D288: lea (Obj05AniData).l,a1 bsr.w Tails_Animate_Part2 bsr.w LoadTailsTailsDynPLC jsr (DisplaySprite).l rts This is where Tails' Tails object gets animated and displayed. Change all this to: Code (ASM): loc_1D288: lea (Obj05AniData).l,a1 bsr.w Tails_Animate_Part2 bsr.w LoadTailsTailsDynPLC movea.w parent(a0),a1 ; Move Tails' register to a1 move.w invulnerable_time(a1),d0 ; Move Tails' invulnerable time to d0 beq.s + ; Is invulnerable_time 0? If so, always display his tails addq.w #1,d0 ; Make d0 the same as old invulnerable_time's d0 lsr.w #3,d0 ; Shift bits to the right 3 times bcs.s + ; If the Carry bit is set, branch and display his tails rts ; Otherwise, do not display Tails' tails + jmp (DisplaySprite).l ; Display Tails' tails Done. Sonic 3 and Knuckles fix - SVN Disassembly Go to "loc_1615A:" and you should see this: Code (ASM): loc_1615A: bsr.w Tails_Tail_Load_PLC jmp (Draw_Sprite).l This is where Tails' Tails object gets animated and displayed. Change all this to: Code (ASM): loc_1615A: bsr.w Tails_Tail_Load_PLC movea.w $30(a0),a1 ; Move Tails' register to a1 move.b $34(a1),d0 ; Move Tails' invulnerable time to d0 beq.s + ; Is invulnerable_time 0? If so, always display his tails addq.b #1,d0 ; Make d0 the same as old invulnerable_time's d0 lsr.b #3,d0 ; Shift bits to the right 3 times bcs.s + ; If the Carry bit is set, branch and display his tails rts ; Otherwise, do not display Tails' tails + jmp (Draw_Sprite).l ; Display Tails' tails Done. You should now end up seeing Tails like this: Ta-dah!
This is what I've wanted to see get fixed for as long as I can remember.. Tiddles really needs to implement this in Sonic 3 Complete. Amazing work as usual, RHS.
I know a bug that I don't think has been fixed with his tails. Stand right next to an object, like push against a monitor and then stop. His tails will have his walking/pushing animation while just standing. When you start walking again (or pushing), his tails will have a corrupt frame. Nice job with all these fixes, even though I never notice most of them.
EDIT: Oops, I swear I started typing this before I saw Rika's post. Anyway, visual example of one of the described bugs:
Also his tails disappear when he balances on edges. And when he rolls up the camera offset uses Sonic's value of 5 pixels even though the change in Tails' collision mask size isn't that great, causing a jerk each time he rolls and unrolls (and this includes jumping). And the temporary speed up of the tails animation when he looks up. Tails has a lot of little problems it seems.
Nice fix. The address of the Tails the tails belong to (what?) is already stored in parent(a0)/$3E(a0) in Sonic 2 and $30(a0) in Sonic 3, and this address is copied to a2 earlier in the object code, so you can probably skip loading and checking a1 and just use the defined a2, unless it's already been overwritten by this point (in which case you could just movea.w it back from the SST again rather than checking the player mode). This one at least has been addressed before.
For Tails' tails pushing animation error Are you two talking about this? If so, I've already fixed it a while back (with pictures) SCHG guide (has no pictures) For Tails' tails balancing animation addition I always thought his tails were behind his head, but if you do not like that, then go to "Obj05AniSelection:" and change this bit: Code (ASM): dc.b 0 ; TailsAni_Balance -> Blank Changing that 0 to a $A looks the best IMO, but you can try a different number to suit. For Tails' tails looking up speed animation glitch I've already fixed that also. This post actually explains how to enable debug for Tails, but if you look at the bottom of the post, it will tell you how to fix this animation bug. Actually, here's a quote: Now why didn't I spot that? =P Okay, changed the first post. Update everyone!
Good sir, I ninja'd you. And yes... I get it. I'll get to those pictures. :P BTW, when you said on the balancing fix to change to 6... I somehow think you meant 7. 7 looks MUCH better. 6, the Tails aren't even attached to him. EDIT: And in return you ninja'd me... $A does look better. 7 gives the same look, but with a faster animation... I'd almost prefer 7 in this case... but I guess it's up to the user. OH... found one problem. Using the updated fix... Tails' tails will flash whenever he jumps or rolls, regardless of inv. time.
Wow, the OP fix looks much better; much more like a complete cartoon character. It's funny how it clashes with what I'm used to though.
Yeah, I was basically just idly listing all the Tails glitches I knew about. Not trying to imply that they haven't been fixed before (though some of those guides I had missed before, so thanks). But now I guess with all those links this topic is now the go to place for cleaning up Tails' act.
I have also seen some bugs about Tails having 4 tails behind him sometimes. I'm not sure is it a bug though. I apologise if it isnt related. I try to remember where such errors have occured. E: Found a bug in Sonic 2. When the Emerald Hill 2 boss comes, he drives over Tails' tails.
I implemented it in S3C today and I think the problem is that a2 does get overwritten in the PLC routine, at least in 3. I just cheated and moved the new block to before the PLC load call, which appears to work OK, in this case at least.
It was a school-boy error. I said 6 because in my hack, half the animation indexes are gone (not being used). I wasn't looking at the original Sonic 2. Comparing S2R with S2, 6 = $A. So I changed it to $A =P For Tails' tails priority error glitch (EHZ boss's wheels as example) When I implemented The S3K manager into S2, I thought it only happened then! Anyway, here is a fix, credit to flamewing for this one (see spoiler for fix, or you can see my old post here) Spoiler Step 13 update (15/07/12) - Fix the priority for Tails' tails This bug I only noticed the other day (was also present in S2R). The fix was a bit more involved than I thought. The problem is, Tails' tail's priority has been affected. Even though Tails' priority is $100, and his tails' priority is $100. Here is an example: It seems that his tails are not as much as a priority anymore. Anyway, flamewing had a solution, which he uses for his hack; Sonic 2 Heroes. Anyway, the fix: First, you're going to have to use some RAM. Only a word. So, go to your list of equates. I used $FFFFF5C0 (it's free whether you use the S1 sound driver or not). Call the RAM "Tails_Tails_ptr" Code (ASM): Tails_Tails_ptr = ramaddr( $FFFFF5C0 ) Our new RAM is ready for use. First, go to "InitPlayers:" and under the line: Code (ASM): move.b #2,(Sidekick).w ; load Obj02 Tails object at $FFFFB040 SVN users, yours will say: Code (ASM): move.b #ObjID_Tails,(Sidekick+id).w ; load Obj02 Tails object at $FFFFB040 Insert this: Code (ASM): move.w #Tails_Tails,(Tails_Tails_ptr).w So you have something like this (SVN users, reference only): Code (ASM): move.b #2,(Sidekick).w ; load Obj02 Tails object at $FFFFB040 move.w #Tails_Tails,(Tails_Tails_ptr).w move.w (MainCharacter+x_pos).w,(Sidekick+x_pos).w move.w (MainCharacter+y_pos).w,(Sidekick+y_pos).w subi.w #$20,(Sidekick+x_pos).w addi.w #4,(Sidekick+y_pos).w move.b #8,(Tails_Dust).w ; load Obj08 Tails' spindash dust/splash object at $FFFFD140 Do the same at label "InitPlayers_TailsAlone:", so you have something like this (SVN users, reference only): Code (ASM): InitPlayers_TailsAlone: move.b #2,(MainCharacter).w ; load Obj02 Tails object at $FFFFB000 move.w #Tails_Tails,(Tails_Tails_ptr).w move.b #8,(Tails_Dust).w ; load Obj08 Tails' spindash dust/splash object at $FFFFD100 addi.w #4,(MainCharacter+y_pos).w rts ; End of function InitPlayers Next, go to "loc_A2F2:". This is for when you're at the cutscene at the end of the game. XenoWhirl users. Change this: Code (ASM): loc_A2F2: moveq #$E,d0 move.b #2,(a1) ; load Tails object move.b #$81,$2A(a1) move.b #5,(Object_RAM+$80).w ; load Obj05 (Tails' tails) at $FFFFB080 move.w a1,(Object_RAM+$80+parent).w rts to this: Code (ASM): loc_A2F2: moveq #$E,d0 move.b #2,(a1) ; load Tails object move.b #$81,$2A(a1) move.w #Object_RAM+$80,(Tails_Tails_ptr).w rts SVN users, change this: Code (ASM): loc_A2F2: moveq #$E,d0 move.b #ObjID_Tails,id(a1) ; load Tails object move.b #$81,obj_control(a1) move.b #ObjID_TailsTails,(Tails_Tails_Cutscene+id).w ; load Obj05 (Tails' tails) at $FFFFB080 move.w a1,(Tails_Tails_Cutscene+parent).w rts to this: Code (ASM): loc_A2F2: moveq #$E,d0 move.b #ObjID_Tails,id(a1) ; load Tails object move.b #$81,obj_control(a1) move.w #Tails_Tails_Cutscene,(Tails_Tails_ptr).w ; Tails' tails at $FFFFB080 rts Next, go to "Obj02_Init_Continued:", and change the last few lines. Change this: Code (ASM): move.b #5,(Tails_Tails).w ; load Obj05 (Tails' Tails) at $FFFFD000 move.w a0,(Tails_Tails+parent).w ; set its parent object to this SVN users, yours will say: Code (ASM): move.b #ObjID_TailsTails,(Tails_Tails+id).w ; load Obj05 (Tails' Tails) at $FFFFD000 move.w a0,(Tails_Tails+parent).w ; set its parent object to this And change it to this: Code (ASM): movea.w (Tails_Tails_ptr).w,a1 move.b #5,0(a1) ; load Obj05 (Tails' Tails) at $FFFFD000 move.w a0,parent(a1) ; set its parent object to this And change it to this: Code (ASM): movea.w (Tails_Tails_ptr).w,a1 move.b #ObjID_TailsTails,id(a1) ; load Obj05 (Tails' Tails) move.w a0,parent(a1) ; set its parent object to this One more step! Go to "Obj02:" See the command jmp Obj02_States(pc,d1.w) (jmp Obj02_Index(pc,d1.w))? Change the "jmp" to a "jsr". And directly underneath it, add this: Code (ASM): movea.w (Tails_Tails_ptr).w,a1 tst.b routine(a1) beq.s + jmp (DisplaySprite2).l + rts So you have something like this (SVN users, reference only): Code (ASM): Obj02: ; a0=character cmpi.w #2,(Player_mode).w bne.s + move.w (Camera_Min_X_pos).w,(Tails_Min_X_pos).w move.w (Camera_Max_X_pos).w,(Tails_Max_X_pos).w move.w (Camera_Max_Y_pos_now).w,(Tails_Max_Y_pos).w + moveq #0,d0 move.b routine(a0),d0 move.w Obj02_States(pc,d0.w),d1 jsr Obj02_States(pc,d1.w) movea.w (Tails_Tails_ptr).w,a1 tst.b routine(a1) beq.s + jmp (DisplaySprite2).l + rts Done! Tails' tails should now work with the right priority! Tails will now queue his tails for drawing right after himself. Without this, the tails will be queued for drawing after all objects between Tails and the tails that have the same priority. And that's why before, Tails' tails had less priority. Reverted the original guide back to using a1, just so everyone can understand it better. EDIT: Added an index to my first post for quick access and changed the title to the topic.
Surely it'd still be better to movea.w parent(a0),a1 (S2) or movea.w $30(a0),a1 (S3), as the object originally did to a2, rather than recalculating it from scratch based on the player mode?
Just tried it, seems to work fine with no side-effects. Saves a bit of time not comparing with the player_mode. Cheers, will change the first post... again =P