Sonic and Sega Retro Message Board: Some changes and fixes for Sonic 2 - Sonic and Sega Retro Message Board

Jump to content

Hey there, Guest!  (Log In · Register) Help
  • 16 Pages +
  • ◄ First
  • 14
  • 15
  • 16
    Locked
    Locked Forum

Some changes and fixes for Sonic 2

#226 User is offline Clownacy 

Posted 06 October 2017 - 06:17 PM

  • Posts: 739
  • Joined: 06-July 13
  • Gender:Not Telling
Ever notice how rings disappear while still onscreen if you move them offscreen slightly, but only off the top of the screen? I sure didn't until my last playthrough. Anyhow, it looks like this was fixed in S3K, so let's just do what that does.

The code that causes this is under BuildRings:

	move.w	4(a0),d2	; get ring Y pos
	sub.w	4(a3),d2	; subtract camera Y pos
	andi.w	#$7FF,d2
	addi_.w	#8,d2
	bmi.s	BuildRings_NextRing	; dunno how this check is supposed to work
	cmpi.w	#240,d2
	bge.s	BuildRings_NextRing	; if the ring is not on-screen, branch


What's important to note is how d2 is AND'd, and then 8 is added to it. The reason this is a problem is, consider that the ring is slightly offscreen: d2 will be $FFFF or so, which, after ANDing, becomes $7FF. Now, when adding 8 to it, it won't wrap back around to $0007, but $0807. It's also worth noting that the 'bmi' there is broken, also because of the position of this AND.

That said, the solution is pretty obvious: just move the 'andi' to before the 'cmpi' instead.

EDIT: Bonus change - Rings don't shake with the rest of the screen in places like the HTZ earthquake sequencies. If you want to correct this (like S3K looks like it did), just change the 'lea (Camera_X_pos).w,a3' to 'lea (Camera_X_pos_copy).w,a3'.
This post has been edited by Clownacy: 06 October 2017 - 06:27 PM

#227 User is offline Clownacy 

Posted 29 October 2018 - 05:21 PM

  • Posts: 739
  • Joined: 06-July 13
  • Gender:Not Telling
...It's seriously been a year? Anyway, there's this one really annoying bug where if you enter Debug Mode underwater, and then exit it above-water, Sonic will still have his underwater physics.

This is because Sonic will only trigger his 'exiting water' code if he's above the water's Y-coordinate and his 'is underwater' flag is set. The problem is, when Sonic exits Debug Mode, it clears his 'is underwater' flag. This happens in sub_41CB8:

; sub_41CB8:
Debug_ResetPlayerStats:
	move.b	d0,anim(a1)
	move.w	d0,2+x_pos(a1) ; subpixel x
	move.w	d0,2+y_pos(a1) ; subpixel y
	move.b	d0,obj_control(a1)
	move.b	d0,spindash_flag(a1)
	move.w	d0,x_vel(a1)
	move.w	d0,y_vel(a1)
	move.w	d0,inertia(a1)
	; note: this resets the 'is underwater' flag, causing the bug where
	; if you enter Debug Mode underwater, and exit it above-water, Sonic
	; will still move as if he's underwater
	move.b	#2,status(a1)
	move.b	#2,routine(a1)
	move.b	#0,routine_secondary(a1)
	rts
; End of function Debug_ResetPlayerStats



As the comment points out, it's that 'move.b #2,status(a1)' line. To fix the bug, the 6th bit of Sonic's status needs to be preserved, like this:

	andi.b	#1<<6,status(a1)
	ori.b	#2,status(a1)



Funnily enough, this bug doesn't exist in Sonic 1 since Debug Mode resets way fewer variables.
This post has been edited by Clownacy: 29 October 2018 - 07:38 PM

#228 User is offline biggestsonicfan 

Posted 29 October 2018 - 08:14 PM

  • Model2wannaB
  • Posts: 742
  • Joined: 09-May 07
  • Gender:Male
  • Project:Formerly Sonic the Fighters

View Postredhotsonic, on 07 June 2012 - 05:00 PM, said:

Something Cool for CPZ boss!

THIS IS JUST FOR LAUGHS, but I thought I'd share it anyway! Back at the label "loc_2E692:". See these two lines?

	btst	#2,$2D(a1)
	beq.s	loc_2E6CA


Comment them out! And everytime Eggman drops the gunge, this will happen!

Posted Image


Well, I found it funny =P

Since I just found this thread, can this be converted into a GameGenie code for use on hardware? I have an itching to try it out but I've never compiled S2 from scratch and feel that the time and effort spent would decrease my overall enjoyment levels.

I plan to go through this whole thread because it's absolutely fascinating. I'd love to do stuff to Sonic the Fighters like this once I understand it a little better (and I finish my decompile).

EDIT1: Actually it would make more sense to have it implemented as Esrael had it, but the download link is broken. :argh:
This post has been edited by biggestsonicfan: 29 October 2018 - 08:20 PM

#229 User is offline Wafer 

Posted 30 October 2018 - 04:14 PM

  • Posts: 8
  • Joined: 28-November 17

View Postbiggestsonicfan, on 29 October 2018 - 08:14 PM, said:

Since I just found this thread, can this be converted into a GameGenie code for use on hardware? I have an itching to try it out but I've never compiled S2 from scratch and feel that the time and effort spent would decrease my overall enjoyment levels.

I plan to go through this whole thread because it's absolutely fascinating. I'd love to do stuff to Sonic the Fighters like this once I understand it a little better (and I finish my decompile).

EDIT1: Actually it would make more sense to have it implemented as Esrael had it, but the download link is broken. :argh:/>

Honestly, don't be intimidated by the prospect of building from assembly. It's just downloading the source from Github and running build.bat. You could do it in like 5 minutes, and then you'll be able to look at doing other fixes yourself, and maybe move onto your own ideas.

#230 User is offline Clownacy 

Posted Yesterday, 04:50 AM

  • Posts: 739
  • Joined: 06-July 13
  • Gender:Not Telling
This vine switch.

Posted Image

I'm sure some of you know exactly what bug I'm about to describe. Normally, when you press a button to release yourself from a vine, you jump. But not this one. If you try to jump off too soon, you drop like a rock.

So why? Well, believe it or not, the issue isn't with the vine object, but that drawbridge next to it.

This object's interesting: it uses the multi-sprite system to draw all of its sprites using only one object. Sonic 1 lacked this feature, meaning the bridges in GHZ are actually multiple objects, one for each segment.

The multi-sprite system works by turning most of the object's RAM into an array of sprite metadata. But the drawbridge object needs that RAM for other things. Its solution? Make the bridge use two objects instead: one master object that controls everything, and one sprite-mule object whose only purpose is to store sprite data.

So if the drawbridge is made up of multiple sprites, does that mean its collision is made up of numerous small hitboxes as well?

No. The object only uses one hitbox. Depending on what angle the drawbridge is pointing, the hitbox is either a thin vertical box, or a thin horizontal one. This means the drawbridge's appearance doesn't reflect its hitbox at all: if the bridge is at 45 degress, the hitbox will actually behave as if it's at 0.

So when does the hitbox swap? Well, it's set according to this code...

loc_2A18A:
	move.w	#$13,d1	; width
	move.w	#$40,d2	; height
	move.w	#$41,d3	; other height
	move.b	angle(a0),d0
	beq.s	loc_2A1A8
	cmpi.b	#$40,d0
	beq.s	loc_2A1B4
	cmpi.b	#-$40,d0
	bhs.s	loc_2A1B4

loc_2A1A8:
	move.w	#$4B,d1	; width
	move.w	#8,d2	; height
	move.w	#9,d3	; other height

loc_2A1B4:


angle(a0) is... the angle, only the range is 0-256 instead of 0-360, so $40 is 90 and -$40 ($C0) is 270.

At 0 degrees, the bridge is pointing to the right, at 90, it's pointing down. So, if the bridge is pointing straight down, or between up and right, it uses its vertical hitbox. Otherwise, it uses its horizontal one.

The problematic drawbridge spawns pointing down, and moves to point right after you pull the switch. So, in effect, the moment the bridge moves just one degree, it should change its hitbox, basically allowing you to walk straight through the drawbridge if you're fast enough.

So where is this hitbox? It actually belongs to the invisible master object, so the hitbox should be whereever that is. But it's invisible... at least until I do a little hackery. So I change that, and...

Posted Image

Oh dear.

Like I said, the moment the drawbridge starts moving, the hitbox switches from a tall one to a wide one, but the object where the hitbox applies to is still in the tall position. That's why you drop like a rock: the vine object releases you, only for the game to realise you're embedded in a solid object's hitbox, and push you down.

It's not until the drawbridge finishes moving that the master object updates its position, and applies collision to the correct area. The reason it waits is because of a different drawbridge, which spawns pointing up, and points right after you pull the switch. In that case, if the master object moves right away, then you'd be able to walk on an invisible bridge before the real one even gets there.

Oddly enough, this doesn't apply to the bridges that point up and move to the left instead: those change collision instantly. Or at least, they try to. You know what bridge points up, moves left, and has this same dropping-like-a-rock bug? The one above The Pit. But yeah, this one actually does change its collision and position immediately, but for some reason it only updates the object's X coordinate, meaning the hitbox still floats in the air, ready to bump Sonic's head. It doesn't even set the object's collision width properly, meaning even if it was positioned properly, Sonic would still fall through it if he tried walking on it.

This object really does feel broken and unfinished. Why would the up-to-left version change collision right away, but not the up-to-right one?

Here's my best attempt at fixing the "intended" behaviour:

Go to Obj81_BridgeUp, and replace this:

	cmpi.b	#$81,status(a0)
	bne.s	+
	move.w	objoff_30(a0),x_pos(a0)
	subi.w	#$48,x_pos(a0)
+


With this:

	move.b	status(a0),d0
	andi.b	#3,d0
	beq.s	+
	move.b	#$40,width_pixels(a0)
	move.w	objoff_32(a0),y_pos(a0)
	move.w	objoff_30(a0),x_pos(a0)
	moveq	#$48,d0
	btst	#1,status(a0)
	beq.s	.notyflipped
	neg.w	d0
.notyflipped:
	btst	#0,status(a0)
	beq.s	.notxflipped
	neg.w	d0
.notxflipped:
	add.w	d0,x_pos(a0)
+


But yeah, I don't think this behaviour's right at all. Being able to walk on a bridge that isn't there yet just doesn't feel right. Meanwhile, being blocked by an upside-down bridge that isn't even in the way isn't right either. So in my opinion, the normal bridges shouldn't change collision instantly, but the upside-down ones should.

To correct this, replace the above block of code with this instead:

	btst	#1,status(a0)
	beq.s	+
	move.b	#$40,width_pixels(a0)
	move.w	objoff_32(a0),y_pos(a0)
	move.w	objoff_30(a0),x_pos(a0)
	moveq	#$48,d0
	btst	#0,status(a0)
	beq.s	.notxflipped
	neg.w	d0
.notxflipped:
	add.w	d0,x_pos(a0)
+


This changes the master object repositioning. To change the hitbox-swapping, go to loc_2A18A and replace this:

	move.b	angle(a0),d0
	beq.s	loc_2A1A8
	cmpi.b	#$40,d0
	beq.s	loc_2A1B4
	cmpi.b	#-$40,d0
	bhs.s	loc_2A1B4


With this:

	move.b	angle(a0),d0
	cmpi.b	#$40,d0
	beq.s	loc_2A1B4	; Straight down
	cmpi.b	#$80,d0
	bhi.s	loc_2A1B4	; Anywhere upwards between left and right

This post has been edited by Clownacy: Yesterday, 04:52 AM

  • 16 Pages +
  • ◄ First
  • 14
  • 15
  • 16
    Locked
    Locked Forum

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