Tuesday, August 22, 2017

Dynamic resize routines

Along with the camera bound variables we saw last time, there are also four matching "target" values, which are meant to smoothly change a level's size, such as after a boss fight. However, in Sonic 3, only Camera_target_max_Y_pos is wired up, and the other three do absolutely nothing. The code which gradually moves Camera_max_Y_pos towards its target position is in the Do_ResizeEvents function.
    Camera_target_min_X_pos = ramaddr( $FFFFEE0C ) ; word
    Camera_target_max_X_pos = ramaddr( $FFFFEE0E ) ; word
    Camera_target_min_Y_pos = ramaddr( $FFFFEE10 ) ; word
    Camera_target_max_Y_pos = ramaddr( $FFFFEE12 ) ; word
The Do_ResizeEvents function is also responsible for running each level's dynamic resize routines. These are called once every frame, and serve as a place where each stage can run logic to modify the level size based on the camera's current position.
loc_1CA20:
    cmpi.w  #$740,(Camera_X_pos).w
    blo.s   locret_1CA3A
    cmpi.w  #$400,(Camera_Y_pos).w
    bhs.s   locret_1CA3A
    move.w  #$740,(Camera_min_X_pos).w
    addq.b  #2,(Dynamic_resize_routine).w

locret_1CA3A:
    rts
For instance, in the routine for Icecap Zone 2 above, the game checks if the camera's X position is $740 or greater, and if so, locks the left boundary at the act 1 boss area. Note how it doesn't happen when the camera's Y position is greater than $400 for some reason: as a result, Knuckles can backtrack all the way to the pre-boss star post.


Similarly to "old"-style objects, resize routines behave like a state machine, with the current routine selected through an index byte stored somewhere in RAM. This byte is saved when you touch a star post or a special stage ring, so that the level is always in the appropriate state when the player respawns.
ICZ1_Resize:
    moveq   #0,d0
    move.b  (Dynamic_resize_routine).w,d0
    move.w  off_1C9DA(pc,d0.w),d0
    jmp     off_1C9DA(pc,d0.w)
; ---------------------------------------------------------------------------
off_1C9DA:
    dc.w loc_1C9E0-off_1C9DA
    dc.w loc_1C9FA-off_1C9DA
    dc.w locret_1CA0C-off_1C9DA
; ---------------------------------------------------------------------------
Much like the camera target variables though, dynamic resize routines have fallen out of style in the Sonic 3 codebase, with few stages actually using them. None of the stages in the Sonic & Knuckles half of the game have resize routines, but the system has to be carried around for backwards compatibility with the Sonic 3 stages.
LevelResizeArray:
    dc.w AIZ1_Resize-LevelResizeArray
    dc.w AIZ2_Resize-LevelResizeArray
    dc.w HCZ1_Resize-LevelResizeArray
    dc.w HCZ2_Resize-LevelResizeArray
    dc.w MGZ_Resize-LevelResizeArray
    dc.w MGZ_Resize-LevelResizeArray
    dc.w No_Resize2-LevelResizeArray
    dc.w No_Resize2-LevelResizeArray
    dc.w No_Resize2-LevelResizeArray
    dc.w No_Resize2-LevelResizeArray
    dc.w ICZ1_Resize-LevelResizeArray
    dc.w ICZ2_Resize-LevelResizeArray
    dc.w No_Resize-LevelResizeArray
    dc.w LBZ2_Resize-LevelResizeArray
    dc.w No_Resize3-LevelResizeArray
    dc.w No_Resize3-LevelResizeArray
    dc.w No_Resize3-LevelResizeArray
    dc.w No_Resize3-LevelResizeArray
    ...

No comments:

Post a Comment