GHZ Vertical Scrolling Fix - RetroKoH/S1Fixed GitHub Wiki
(Original guide by OrionNavattan)
Source: Sonic Retro thread
Commit: 9983e8e
This may very well be more of a design choice change than a fix, per se, but I'm listing it as a fix, reason being that just because something is intended, doesn't mean it can't be fixed. The background scrolling code for GHZ calculates the VScroll values in a way that doesn't make sense. The code below is from Revision 1 (which S1Fixed uses), but Revision 0 is similar.
; calculate Y position
lea (v_hscrolltablebuffer).w,a1
move.w (v_screenposy).w,d0 ; get screen pos
andi.w #$7FF,d0 ; maximum $7FF
lsr.w #5,d0 ; divide by $20
neg.w d0
addi.w #$20,d0
bpl.s .limitY
moveq #0,d0
.limitY:
move.w d0,d4
move.w d0,(v_bgscrposy_vdp).w
;...
The VScroll value varies inversely in relation to the camera y-pos: the maximum VScroll value of $20 is applied if the y-pos is 0, eventually falling to 0 once the camera reaches $400. This has the effect of the background scrolling in the "wrong" direction in relation to the camera, moving down as the camera rises, and up as the camera falls. While this may have been a deliberate design choice, I don't think it looks right. The following code makes the background scroll in the "correct" direction:
; calculate Y position
lea (v_hscrolltablebuffer).w,a1
move.w (v_screenposy).w,d0 ; get screen pos
andi.w #$7FF,d0 ; maximum $7FF
lsr.w #5,d0 ; divide by $20
cmpi.w #$20,d0
bls.s .limitY ; branch if v_screenposy is between 0 and $400
moveq #$20,d0 ; use $20 if greater
.limitY:
move.w d0,d4
move.w d0,(v_bgscrposy_vdp).w
;...