S3&K Background Deformation in Sonic 1

Discussion in 'Tutorials' started by Stardust Gear, Dec 6, 2019.

  1. Stardust Gear

    Stardust Gear A Programmer Member

    Joined:
    Apr 27, 2014
    Messages:
    134
    Introduction
    The Genesis Sonic trilogy games take advantage of the $200 bytes available in $FFFFA800 for background scrolling.
    Sonic 1 and 2 occasionally use this buffer for fixed 16px block scroll, but S3&K supports arbitrary block sizes, and a special mode for 1px line scrolling, e.g. for water deformation.
    This approach is more efficient and easier to use, because you can split the background to any number of parallax blocks, each one with any size.

    Format
    The background deformation routine uses a block size table, each word defining a block. The block's Y position starts from 0 in the background layout, and is equal to the total size of the previous blocks.
    The block size can be 1 to $7FFF pixels, with bit 15 defining the deformation mode:
    • Bit 15 clear - Normal block scroll.
    • Bit 15 set - Pixelwise block scroll, meaning each 1px line has its own x-position word in the buffer. The number of lines is the block size, with bit 15 clear.
    The buffer consists of words that define the absolute x-position of each block (or pixel in pixelwise blocks), in sequential order, matching the block size table.

    How to Use
    In the DeformLayers routine for the level, calculate the y-position of the entire background, and call the Bg_Scroll_Y routine to ensure the correct tiles are loaded when you move vertically.
    Copy the background y-position for the deformation routine.

    Calculate the x-position of each scroll block/line, and write into the buffer in $FFFFA800.
    For example, load the camera x-position and perform various shift and addition instructions and for-loops.

    Finally, load the block size table and buffer addresses, and call the ProcessBGScroll routine.
    The entire deformation routine may look like this:
    Code:
        move.w    (v_scrshifty).w,d5    ; (y_new - y_last) * $100
        ext.l    d5
        asl.l    #7,d5            ; 50% vertical scrolling
        bsr.w    Bg_Scroll_Y
        move.w    (v_bgscreenposy).w,(v_bgscrposy_dup).w
        lea    (v_bgscroll_buffer).w,a1    ; $FFFFA800
        ; ... calculate block x-position ...
        lea    (BGScrollSize_xxZ).l,a4
        lea    (v_bgscroll_buffer).w,a5
        jmp    ProcessBGScroll
    
    
    ProcessBGScroll will look at the buffer, and compute the horizontal scroll buffer data according to the foreground and background block positions.

    Porting to Sonic 1
    Download the code here, and include it anywhere in the disassembly.
    Assuming you have a recent S1 GitHub disassembly, the modified S1 files are here:
    DeformLayers and BGScrollSizes files

    Replace the "_inc/DeformLayers.asm" or "_inc/DeformLayers (JP1).asm", according the revision, with the new file.
    Include the "BGScrollSizes.asm" file in the source code.
    Done!

    Working S1 ROM

    Notes
    • This doesn't yet support water levels with water deformation.
    • Preferably use a 512px wide background, since LoadTilesAsYouMove loads background tiles based on a hardcoded pattern for each level.
     
    Last edited: Jan 20, 2020