Actions

SCHG How-to

Difference between revisions of "Fix the camera follow bug"

From Sonic Retro

m (Replacing removed nonworking BBCode with what appears to be original author's intention)
Line 5: Line 5:
 
==Explaining the issue==
 
==Explaining the issue==
  
The engine that allows the screen to follow Sonic has the responsibility of ensuring that the screen does not move more than 10 (hex) pixels any direction at one time, this is to allow the draw code to draw the lines of 16x16 blocks correctly without skipping any lines, this means that if Sonic is away from the screen's "central box" position by less than 10 (hex) pixels, then the screen's "central box" will move directly to Sonic, if however, Sonic is further than that, the screen will move at a maximum of 10 (hex) pixels in the direction it is suppose to be moving to.  The routine "ScrollVertical:" handles this for moving the screen up and down, "ScrollHoriz:" on the other hand (or should I say "ScrollHoriz2:") handles this for the screen moving right, but not when moving left.
+
The engine that allows the screen to follow Sonic has the responsibility of ensuring that the screen does not move more than 10 (hex) pixels any direction at one time, this is to allow the draw code to draw the lines of 16x16 blocks correctly without skipping any lines, this means that if Sonic is away from the screen's "central box" position by less than 10 (hex) pixels, then the screen's "central box" will move directly to Sonic, if however, Sonic is further than that, the screen will move at a maximum of 10 (hex) pixels in the direction it is suppose to be moving to.  The routine "ScrollVertical:" handles this for moving the screen up and down, "ScrollHoriz:" on the other hand (or should I say "ScrollHoriz2:") handles this for the screen moving right, but '''not''' when moving left.
  
 
==Fixing the issue==
 
==Fixing the issue==

Revision as of 11:04, 10 October 2013

(Original guide by MarkeyJester)

This bug is almost unnoticable in the original game, if you are to write your own special screen movements that cause the screen to move away from Sonic, and then let the engine move the screen back to Sonic, then it can become noticable

Explaining the issue

The engine that allows the screen to follow Sonic has the responsibility of ensuring that the screen does not move more than 10 (hex) pixels any direction at one time, this is to allow the draw code to draw the lines of 16x16 blocks correctly without skipping any lines, this means that if Sonic is away from the screen's "central box" position by less than 10 (hex) pixels, then the screen's "central box" will move directly to Sonic, if however, Sonic is further than that, the screen will move at a maximum of 10 (hex) pixels in the direction it is suppose to be moving to. The routine "ScrollVertical:" handles this for moving the screen up and down, "ScrollHoriz:" on the other hand (or should I say "ScrollHoriz2:") handles this for the screen moving right, but not when moving left.

Fixing the issue

Observe the code for right movement:

<asm>loc_65CC: cmpi.w #$10,d0 ; <- Restriction bcs.s loc_65D6 ; <- Restriction move.w #$10,d0 ; <- Restriction

loc_65D6: add.w ($FFFFF700).w,d0 cmp.w ($FFFFF72A).w,d0 blt.s loc_65E4 move.w ($FFFFF72A).w,d0</asm> As you can see by the code marked "Restriction", this is to prevent the screen from moving right by 10 pixels, thereas if we look at the code for left movement:

<asm>loc_65F6: add.w ($FFFFF700).w,d0 cmp.w ($FFFFF728).w,d0 bgt.s loc_65E4 move.w ($FFFFF728).w,d0 bra.s loc_65E4</asm> The "Restriction" does not exist, the fix is moderately simple:

<asm>loc_65F6: cmpi.w #$FFF0,d0 ; has the screen moved more than 10 pixels left? bcc.s Left_NoMax ; if not, branch move.w #$FFF0,d0 ; set the maximum move distance to 10 pixels left

Left_NoMax: add.w ($FFFFF700).w,d0 cmp.w ($FFFFF728).w,d0 bgt.s loc_65E4 move.w ($FFFFF728).w,d0 bra.s loc_65E4</asm>

Horizontal wrapping bug-fix

There is another bug related to this which funnily enough is also related to the good old "screen wrapping vertically" bug in Sonic 2 and up, but this is to do with horizontal rather than vertical, at routing "ScrollHoriz2:" we have:

<asm>ScrollHoriz2: ; XREF: ScrollHoriz move.w ($FFFFD008).w,d0 sub.w ($FFFFF700).w,d0 subi.w #$90,d0 bcs.s loc_65F6 subi.w #$10,d0 bcc.s loc_65CC clr.w ($FFFFF73A).w rts </asm> bcc and bcs are unsigned branches, the problem here is that if Sonic is behind the screen (I.e. to the left), the result will be negative (I.e. a value from 8000 to FFFF), but with the unsigned branches it will obviously treat 8000 to FFFF as positive and higher than 7FFF, thus it believes it has to move right rather than left, the fix is also simple, change the unsigned branch conditions with signed branch conditions:

<asm>ScrollHoriz2: ; XREF: ScrollHoriz move.w ($FFFFD008).w,d0 sub.w ($FFFFF700).w,d0 subi.w #$90,d0 bmi.s loc_65F6 ; cs to mi (for negative) subi.w #$10,d0 bpl.s loc_65CC ; cc to pl (for negative) clr.w ($FFFFF73A).w rts </asm> The cc to pl should not matter, but it's best to be safe.