My first post ... Hello everyone ! Did you ever notice some inconsistency of Bombs size in Sonic 2 special stage ? A simple line of objects show differents bomb size at same z position : Bombs are not intended to be that small, look at their much bigger shadows ! Here's the explaination: z_pos of objects in special stage is managed by objoff_30 : $1 is front of camera, the higher the value, the more distant the object The following code set the animation of the Bomb based on z_pos : Code (ASM): loc_35150: cmpi.b #$A,anim(a0) beq.s return_3516A ; return if explosion, no need to scale the object move.w objoff_30(a0),d0 cmpi.w #$1D,d0 ble.s loc_35164 moveq #$1E,d0 ; cap the most distant value loc_35164: move.b byte_35180(pc,d0.w),anim(a0) ; set new animation return_3516A: rts ; =========================================================================== loc_3516C: move.l (sp)+,d0 move.l objoff_34(a0),d0 beq.w JmpTo63_DeleteObject movea.l d0,a1 ; a1=object st objoff_2A(a1) if removeJmpTos JmpTo63_DeleteObject ; JmpTo endif jmpto (DeleteObject).l, JmpTo63_DeleteObject ; =========================================================================== byte_35180: dc.b 9, 9, 9, 8, 8, 7, 7, 6, 6, 5, 5, 4, 4, 3, 3, 3 dc.b 2, 2, 2, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0; 16 ; =========================================================================== The table byte_35180 defines animation id, the values are OK. So why bombs are sometimes small when they are near Camera ? Have a look at Bomb animation script : Code (ASM): ; animation script: ; off_364CE: Ani_obj61: offsetTable offsetTableEntry.w byte_364E4 ; 0 offsetTableEntry.w byte_364E7 ; 1 offsetTableEntry.w byte_364EA ; 2 offsetTableEntry.w byte_364ED ; 3 offsetTableEntry.w byte_364F0 ; 4 offsetTableEntry.w byte_364F3 ; 5 offsetTableEntry.w byte_364F6 ; 6 offsetTableEntry.w byte_364F9 ; 7 offsetTableEntry.w byte_364FC ; 8 offsetTableEntry.w byte_364FF ; 9 offsetTableEntry.w byte_36502 ; $A byte_364E4: dc.b $B, 0,$FF rev02even byte_364E7: dc.b $B, 1,$FF rev02even byte_364EA: dc.b $B, 2,$FF rev02even byte_364ED: dc.b $B, 3,$FF rev02even byte_364F0: dc.b $B, 4,$FF rev02even byte_364F3: dc.b $B, 5,$FF rev02even byte_364F6: dc.b $B, 6,$FF rev02even byte_364F9: dc.b $B, 7,$FF rev02even byte_364FC: dc.b $B, 8,$FF rev02even byte_364FF: dc.b $B, 9,$FF rev02even byte_36502: dc.b 2, $A, $B, $C,$FF even anim: $0 is small bomb, $9 is biggest bomb, $A is explosion The animation duration is $B with only one image. Now the animation routine : Code (ASM): loc_3539E: subq.b #1,anim_frame_duration(a0) bpl.s return_353E8 ; even if new anim is set, frame will not be updated until frame duration reach -1 moveq #0,d0 move.b anim(a0),d0 add.w d0,d0 adda.w (a1,d0.w),a1 move.b (a1),anim_frame_duration(a0) moveq #0,d1 move.b anim_frame(a0),d1 move.b 1(a1,d1.w),d0 bpl.s loc_353CA move.b #0,anim_frame(a0) move.b 1(a1),d0 loc_353CA: andi.b #$7F,d0 move.b d0,mapping_frame(a0) move.b status(a0),d1 andi.b #3,d1 andi.b #$FC,render_flags(a0) or.b d1,render_flags(a0) addq.b #1,anim_frame(a0) return_353E8: rts Here it is : even if new anim is set, frame will not be updated until frame duration reach -1 As the animation last 12 frames, it will skip a lot of values in byte_35180 table ! To complete this analysis, the following code explain why shadows scale is ok. It is simply linked to the animation of the parent object. Code (ASM): loc_3534E: moveq #9,d0 sub.b anim(a1),d0 A simple fix is to set animation duration to 0 instead of $B, now it looks like this : No more tiny Bombs ... So why the animation duration is $B ? - maybe a last time adjustment to lower the size of bombs (instead of setting different values in byte_35180 ?) - maybe bombs had animations that were removed This bug also applies to Rings that use the same animation routine ... but as their anim duration is 5, it is much less visible. A better fix to this bug is to modify the animation routine for sure !
Oh my absolute fucking god... I am so surprised at how this is easily missed! Well done for not only noticing, but also for finding a fix!
That is very well spotted! This is true for bombs, rings, and... the Chaos Emerald. Now, this is beautiful (and animation is smooth): I have a more polished fix to propose. In loc_35164, save the last animation value in the unused byte $23 of the bomb/ring/emerald object. Possibly, the animation value will be updated the following line: Code (ASM): loc_35164: move.b anim(a0),$23(a0) move.b byte_35180(pc,d0.w),anim(a0) In loc_3539E, test $23 with the current animation value (that possibly changed above). If the values are not the same, skip the test on the frame duration. Then, reset $23 with the current animation value: Code (ASM): loc_3539E: move.b $23(a0),d0 cmp.b anim(a0),d0 bne.s .skip subq.b #1,anim_frame_duration(a0) bpl.s return_353E8 .skip: move.b anim(a0),$23(a0) moveq #0,d0
Sorry to bring this forum up again, but I think what I say might help someone who wants to make a proper fix Since I suck at coding, I decided to just remove the code causing the animation issue (loc_3539E). The rings spaz out out due to having an animation and using the same code, but this does fix the bomb size issue, and restores the unused chaos emerald animation. Yep, that's it. By going with this method, our only issue is trying to animate the rings while moving them somewhat smoothly. Maybe we can do that using Hachelle's proposed method?