Sonic and Sega Retro Message Board: MoDule's bugfix guides Vol. 1 - Sonic and Sega Retro Message Board

Jump to content

Hey there, Guest!  (Log In · Register) Help
  • 3 Pages +
  • 1
  • 2
  • 3
    Locked
    Locked Forum

MoDule's bugfix guides Vol. 1 more to come

#31 User is offline flamewing 

Posted 22 July 2011 - 03:36 PM

  • Emerald Hunter
  • Posts: 831
  • Joined: 11-October 10
  • Gender:Male
  • Location:Brasil
  • Project:Sonic Classic Heroes; Sonic 2 Special Stage Editor; Sonic 3&K Heroes (on hold)
  • Wiki edits:12

View PostMoDule, on 22 July 2011 - 02:41 PM, said:

I'm curious, what was wrong with the original one? The new version is quite different.

As it turns out, it worked around the bug in a way that was as close to fixing it as possible, but without truly fixing it and adding other bugs in the mix. As it was, a character could prevent being scrolled into the boss arena by starting a spindash and not releasing it, for example.

Nice work on the other guides.

#32 User is offline MoDule 

Posted 25 July 2011 - 09:24 AM

  • Posts: 308
  • Joined: 03-October 07
  • Gender:Male
  • Project:Procrastinating from writing bug-fix guides
  • Wiki edits:52

View PostKing, on 03 June 2011 - 11:52 PM, said:

(...) But I'm curious though if any of these fixes can be utilized by the normal gamer using Game Genie or Pro Action Replay codes.

Possible, probably, easy, no. The simplest one I can think of is the roll jump height fix, since all you'd have to do there is replace the offending instructions with NOPs, or ones where you just have to change a number or branch type.

View Postflamewing, on 22 July 2011 - 03:36 PM, said:

As it turns out, it worked around the bug in a way that was as close to fixing it as possible, but without truly fixing it and adding other bugs in the mix. As it was, a character could prevent being scrolled into the boss arena by starting a spindash and not releasing it, for example.

Ah yes, that makes sense.

View Postflamewing, on 22 July 2011 - 03:36 PM, said:

Nice work on the other guides.

Now I just have to write them...

#33 User is offline Elratauru 

Posted 25 July 2011 - 02:59 PM

  • Oooh Shiny stuff! don't touch it >:(
  • Posts: 960
  • Joined: 13-April 08
  • Gender:Male
  • Location:Montevideo, Uruguay
  • Project:Web Developer
  • Wiki edits:132
Thank you for this! I just noticed the jump rolling 5-px thing bug and that explained why my old Flash Sonic engine did that sometimes :P!

Even though Im not gonna use it for hacking, it will come handy for future updates and re-writes of that old engine! :)

#34 User is offline MoDule 

Posted 05 May 2012 - 03:00 PM

  • Posts: 308
  • Joined: 03-October 07
  • Gender:Male
  • Project:Procrastinating from writing bug-fix guides
  • Wiki edits:52
Since it's been a while, I thought I'd post a new little bug fix I just finished. No wiki this time, sorry. If someone would be kind enough to volunteer to wiki this, I'd be very thankful. Otherwise, I'd just take care of it myself, (whe)never.
What I've got this time is a bug I've actually already posted partial fixes for in the past and even made a slightly better fix recently. Pretty much out of the blue, a much more elegant solution came to me just a few minutes ago.

The bug: The player object's speed values behave inconsistently when entering and exiting water. For instance, if a player falls into water while speed shoes are active, the sped up movement stats will be lost; should the power up run out under water, then the player will receive above water normal stats. This bug exists in all of the four main series games.

The fix (s2 semi recent hg disassembly):
First, locate Obj01_InWater and comment out or remove a few lines as follows:
	(...)
;	move.w	#$300,(Sonic_top_speed).w
;	move.w	#6,(Sonic_acceleration).w
;	move.w	#$40,(Sonic_deceleration).w
;	tst.b	(Super_Sonic_flag).w
;	beq.s	+
;	move.w	#$500,(Sonic_top_speed).w
;	move.w	#$18,(Sonic_acceleration).w
;	move.w	#$80,(Sonic_deceleration).w
;+
	(...)

Do the same for Obj01_OutWater:
	(...)
;	move.w	#$600,(Sonic_top_speed).w
;	move.w	#$C,(Sonic_acceleration).w
;	move.w	#$80,(Sonic_deceleration).w
;	tst.b	(Super_Sonic_flag).w
;	beq.s	+
;	move.w	#$A00,(Sonic_top_speed).w
;	move.w	#$30,(Sonic_acceleration).w
;	move.w	#$100,(Sonic_deceleration).w
;+
	(...)

It might seem odd to simply remove these lines, as they are what make the players slower/faster under/above water, but the next set of changes should make the solution clear:
Locate Sonic_Move, which should look like this:
Sonic_Move:
	move.w	(Sonic_top_speed).w,d6
	move.w	(Sonic_acceleration).w,d5
	move.w	(Sonic_deceleration).w,d4
	(...)

Underneath the last displayed line, add this:
	btst	#6,status(a0)	; is Sonic under water?
	beq.s	+		; if not, branch
	lsr.w	#1,d4	; reduce stats
	lsr.w	#1,d5
	lsr.w	#1,d6
+

Next, do the same for Sonic_RollSpeed:
	move.w	(Sonic_top_speed).w,d6
	asl.w	#1,d6
	move.w	(Sonic_acceleration).w,d5
	asr.w	#1,d5	; natural roll deceleration = 1/2 normal acceleration
	move.w	#$20,d4	; controlled roll deceleration... interestingly,
			; this should be Sonic_deceleration/4 according to Tails_RollSpeed,
			; which means Sonic is much better than Tails at slowing down his rolling when he's underwater
	btst	#6,status(a0)	; is Sonic under water?
	beq.s	+		; if not, branch
	lsr.w	#1,d5	; reduce stats
	lsr.w	#1,d6
+

and Sonic_ChgJumpDir:
	move.w	(Sonic_top_speed).w,d6
	move.w	(Sonic_acceleration).w,d5
	asl.w	#1,d5
	btst	#6,status(a0)	; is Sonic under water?
	beq.s	+		; if not, branch
	lsr.w	#1,d5	; reduce stats
	lsr.w	#1,d6
+

Finally, in Sonic_RevertToNormal remove the following lines:
	(...)
;	btst	#6,status(a0)	; Check if underwater, return if not
;	beq.s	return_1AC3C
;	move.w	#$300,(Sonic_top_speed).w
;	move.w	#6,(Sonic_acceleration).w
;	move.w	#$40,(Sonic_deceleration).w

Of course, these same changes need to be applied to the other player objects where applicable.
In S3&K, the speed stats are not read or written to directly by the player objects. Instead, the address of the first value is loaded into a4 and the RAM addresses are accessed as follows:
	move.w	#$600,(a4)	; top speed
	move.w	#$C,2(a4)	; acceleration
	move.w	#$80,4(a4)	; deceleration


If this fix is applied, the Wrong speed when transforming under water part of the Super Sonic fixes no longer needs to, or rather, should not be applied.

An explanation: The original problem comes from the fact that there are so many cases to consider when assigning the correct speed values with and without speed shoes and when super. Most of the cases were simply left out. Our fix simply circumvents the problem by calculating the correct under water stats when necessary.

Incidentally, this only works if you wish to preserve the original under water physics, namely making everything half as fast. If for whatever reason someone wants to use a custom set of speed values under water, I will gladly post my previous fix as well.

#35 User is offline Tiddles 

Posted 05 May 2012 - 05:38 PM

  • Diamond Dust
  • Posts: 452
  • Joined: 25-December 09
  • Gender:Male
  • Location:Nottingham, England
  • Project:Get in an accident and wake up in 1973
  • Wiki edits:31
Nice one. I'd been thinking I wanted to fix that pretty soon, so I'll give this a whirl sometime.
Thanks for this, and for the many other bits and pieces I've used from this topic.

#36 User is offline MoDule 

Posted 14 April 2013 - 03:26 PM

  • Posts: 308
  • Joined: 03-October 07
  • Gender:Male
  • Project:Procrastinating from writing bug-fix guides
  • Wiki edits:52
Bit of a big bump, sorry, but I just noticed there's a bug in one of my bug-fixes. The one about the ARZ boss's pillars, to be more precise: this one.
I forgot to clear the pillar object's standing and pushing bits, which would result in characters sliding along the ground, because they'd be put into an in-air state every frame until the pillars are gone. Anyway, that's fixed now.

I'll try and see if I can come up with some new things soon.

#37 User is offline redhotsonic 

Posted 14 April 2013 - 04:04 PM

  • Also known as RHS
  • Posts: 1128
  • Joined: 31-January 05
  • Gender:Male
  • Location:United Kingdom
  • Project:Sonic 2 Recreation
  • Wiki edits:24
Fixing the bug where ARZ boss leaves too early (leaves immediately after the 8th hit) or the DEZ boss when Silver Sonic goes upside down and you can't move on would be a nice addition. I've tried, but no luck so far.

#38 User is offline Tiddles 

Posted 14 April 2013 - 04:06 PM

  • Diamond Dust
  • Posts: 452
  • Joined: 25-December 09
  • Gender:Male
  • Location:Nottingham, England
  • Project:Get in an accident and wake up in 1973
  • Wiki edits:31
By the way, I did apply your latest water fix to S3C, and it works very nicely indeed. :)
There were a couple of other places I had to alter in S3, I think, but I did this ages ago so I can't remember for sure... if anyone's interested I can try to dig it out at some point.

#39 User is offline MoDule 

Posted 14 April 2013 - 04:49 PM

  • Posts: 308
  • Joined: 03-October 07
  • Gender:Male
  • Project:Procrastinating from writing bug-fix guides
  • Wiki edits:52
Speaking of the water fix, I think I might have left out a few edge cases in the original fix. I'll post that one tomorrow.


View Postredhotsonic, on 14 April 2013 - 04:04 PM, said:

Fixing the bug where ARZ boss leaves too early (leaves immediately after the 8th hit) or the DEZ boss when Silver Sonic goes upside down and you can't move on would be a nice addition. I've tried, but no luck so far.
I think someone's already fixed the first one, not sure, though. Never even seen the second one. I'll try giving it a look, can't make any guarantees.

Edit: OK, here's a short writeup on what I changed in my water fix. Let me know if this makes sense. For reference, here's the original guide.
To begin with, let's look at the code in vanilla Sonic 2:

; loc_1A18E:
Obj01_InWater:
	move.w	(Water_Level_1).w,d0
	cmp.w	y_pos(a0),d0	; is Sonic above the water?
	bge.s	Obj01_OutWater	; if yes, branch

	; <-- (1)

	bset	#6,status(a0)	; set underwater flag
	bne.s	return_1A18C	; if already underwater, branch

	movea.l	a0,a1
	bsr.w	ResumeMusic
	move.b	#ObjID_SmallBubbles,(Sonic_BreathingBubbles+id).w ; load Obj0A (sonic's breathing bubbles) at $FFFFD080
	move.b	#$81,(Sonic_BreathingBubbles+subtype).w
	move.l	a0,(Sonic_BreathingBubbles+$3C).w
	move.w	#$300,(Sonic_top_speed).w
	move.w	#6,(Sonic_acceleration).w
	move.w	#$40,(Sonic_deceleration).w
	tst.b	(Super_Sonic_flag).w
	beq.s	+
	move.w	#$500,(Sonic_top_speed).w
	move.w	#$18,(Sonic_acceleration).w
	move.w	#$80,(Sonic_deceleration).w
+
	asr.w	x_vel(a0)
	asr.w	y_vel(a0)	; memory operands can only be shifted one bit at a time

	; <-- (3)

	asr.w	y_vel(a0)
	beq.s	return_1A18C
	move.w	#$100,(Sonic_Dust+anim).w	; splash animation
	move.w	#SndID_Splash,d0	; splash sound
	jmp	(PlaySound).l

What I did in the original guide was to place a check if Sonic is moving upward while entering water at (1) to prevent his y_vel from being lowered. This was so jumping while close to the water surface doesn't unexpectedly lower your jump height. I figured, it's probably better to have such a check for exiting water, as well, even if I can't think of a scenario in which you'd move above the water while falling. So here it is:
In the following code:

; loc_1A1FE:
Obj01_OutWater:
	bclr	#6,status(a0) ; unset underwater flag
	beq.s	return_1A18C ; if already above water, branch

	movea.l	a0,a1
	bsr.w	ResumeMusic
	move.w	#$600,(Sonic_top_speed).w
	move.w	#$C,(Sonic_acceleration).w
	move.w	#$80,(Sonic_deceleration).w
	tst.b	(Super_Sonic_flag).w
	beq.s	+
	move.w	#$A00,(Sonic_top_speed).w
	move.w	#$30,(Sonic_acceleration).w
	move.w	#$100,(Sonic_deceleration).w
+
	cmpi.b	#4,routine(a0)	; is Sonic falling back from getting hurt?
	beq.s	+		; if yes, branch

	; <-- (2)

	asl	y_vel(a0)
+
	tst.w	y_vel(a0)
	beq.w	return_1A18C
	move.w	#$100,(Sonic_Dust+anim).w	; splash animation
	movea.l	a0,a1
	bsr.w	ResumeMusic
	cmpi.w	#-$1000,y_vel(a0)
	bgt.s	+
	move.w	#-$1000,y_vel(a0)	; limit upward y velocity exiting the water
+
	move.w	#SndID_Splash,d0	; splash sound
	jmp	(PlaySound).l
; End of subroutine Sonic_Water

add this:

	tst.w	y_vel(a0)	; is Sonic moving downward?
	bpl.w	return_1A18C	; if yes, don't boost his speed

at the location indicated by (2). Of course, this also needs to be done for Tails and any other characters other than Sonic.
Another thing I experimented with, was to move the check at (1) to the location at (3). This sort of still allows the bug to happen, but it only divides Sonic's y_vel by 2, avoiding the original problem. I'm not sure which one I like better, though.
This post has been edited by MoDule: 15 April 2013 - 05:38 PM

#40 User is offline MoDule 

Posted 16 April 2013 - 03:47 PM

  • Posts: 308
  • Joined: 03-October 07
  • Gender:Male
  • Project:Procrastinating from writing bug-fix guides
  • Wiki edits:52
Double post, so
After tinkering with this a little more, I think I've found something satisfying.
So now my routines look like this:

; loc_1A18E:
Obj01_InWater:
	move.w	(Water_Level_1).w,d0
	cmp.w	y_pos(a0),d0	; is Sonic above the water?
	bge.s	Obj01_OutWater	; if yes, branch

	bset	#6,status(a0)	; set underwater flag
	bne.s	return_1A18C	; if already underwater, branch

	movea.l	a0,a1
	bsr.w	ResumeMusic
	move.b	#ObjID_SmallBubbles,(Sonic_BreathingBubbles+id).w ; load Obj0A (sonic's breathing bubbles) at $FFFFD080
	move.b	#$81,(Sonic_BreathingBubbles+subtype).w
	move.l	a0,(Sonic_BreathingBubbles+$3C).w
	move.w	#$300,(Sonic_top_speed).w
	move.w	#6,(Sonic_acceleration).w
	move.w	#$40,(Sonic_deceleration).w
	tst.b	(Super_Sonic_flag).w
	beq.s	+
	move.w	#$500,(Sonic_top_speed).w
	move.w	#$18,(Sonic_acceleration).w
	move.w	#$80,(Sonic_deceleration).w
+
;	asr.w	x_vel(a0)
;	asr.w	y_vel(a0)	; memory operands can only be shifted one bit at a time
;	asr.w	y_vel(a0)
;-- new stuff starts here
	asr.w	y_vel(a0)	; reduce Sonic's falling speed
	bmi.s	return_1A18C	; if Sonic is moving upward (I.e. from jumping), don't slow him down
	asr.w	x_vel(a0)	; else, slow him down...
	asr.w	y_vel(a0)	; ... and reduce his falling speed more
;-- new stuff ends here
	beq.s	return_1A18C
	move.w	#$100,(Sonic_Dust+anim).w	; splash animation
	move.w	#SndID_Splash,d0	; splash sound
	jmp	(PlaySound).l

Here, I replaced the commented out block with the four lines underneath.
In the other routine, I just moved the check up a few lines:

; loc_1A1FE:
Obj01_OutWater:
	bclr	#6,status(a0) ; unset underwater flag
	beq.s	return_1A18C ; if already above water, branch

	movea.l	a0,a1
	bsr.w	ResumeMusic
	move.w	#$600,(Sonic_top_speed).w
	move.w	#$C,(Sonic_acceleration).w
	move.w	#$80,(Sonic_deceleration).w
	tst.b	(Super_Sonic_flag).w
	beq.s	+
	move.w	#$A00,(Sonic_top_speed).w
	move.w	#$30,(Sonic_acceleration).w
	move.w	#$100,(Sonic_deceleration).w
+
	; <-- here
	tst.w   y_vel(a0)       ; is Sonic moving downward?
	bpl.w   return_1A18C    ; if yes, don't boost his speed

	cmpi.b	#4,routine(a0)	; is Sonic falling back from getting hurt?
	beq.s	+		; if yes, branch
	asl	y_vel(a0)
+
	tst.w	y_vel(a0)
	beq.w	return_1A18C
	move.w	#$100,(Sonic_Dust+anim).w	; splash animation
	movea.l	a0,a1
	bsr.w	ResumeMusic
	cmpi.w	#-$1000,y_vel(a0)
	bgt.s	+
	move.w	#-$1000,y_vel(a0)	; limit upward y velocity exiting the water
+
	move.w	#SndID_Splash,d0	; splash sound
	jmp	(PlaySound).l
; End of subroutine Sonic_Water

I'm probably over-thinking this...

Edit: Just noticed a small bug in my edited InWater routine. I was shifting x_vel(a0) and y_vel(a0) in the wrong order, which caused the branch to return_1A18C to be true when the x_vel is 0, even though it should have been the y_vel. Anyway, I've fixed it in the code block above.
This post has been edited by MoDule: 20 May 2013 - 03:51 PM

  • 3 Pages +
  • 1
  • 2
  • 3
    Locked
    Locked Forum

1 User(s) are reading this topic
0 members, 1 guests, 0 anonymous users