don't click here

Unique Collision Per Act in Sonic 1 (now with Project Sonic: Two-Eight support)

Discussion in 'Engineering & Reverse Engineering' started by Alex Field, Sep 3, 2020.

Tags:
  1. You might remember this guide, it was poorly optimised and takes a lot of cycles; well, after some experimenting I've managed to create a heavily optimised method that doesn't require checking multiple times and shoves everything into a single table.

    At ColIndexLoad:, you'll see this code:
    Code (Text):
    1. ColIndexLoad:                ; XREF: Level
    2.         moveq    #0,d0
    3.         move.b    ($FFFFFE10).w,d0
    4.         lsl.w    #2,d0
    5.         move.l    ColPointers(pc,d0.w),($FFFFF796).w
    6.         rts
    7. ; End of function ColIndexLoad
    What this does grabs the current zone and loads its collision based on what it gets; for example, $00 would be GHZ and $01 LZ. Since we want it per act, replace the code with this:
    Code (Text):
    1. ColIndexLoad:                ; XREF: Level
    2.         move.w    ($FFFFFE10).w,d0
    3.         lsl.b    #6,d0
    4.         lsr.w    #4,d0
    5.         move.l    ColPointers(pc,d0.w),($FFFFF796).w
    6.         rts
    7. ; End of function ColIndexLoad
    This code instead grabs the current act and shifts the entry closer before dividing by 4, resulting in per act collision; then replace the table in Collision index pointers.asm with this:
    Code (Text):
    1.     dc.l Col_GHZ1
    2.     dc.l Col_GHZ2
    3.     dc.l Col_GHZ3
    4.     dc.l Col_GHZ4
    5.     dc.l Col_LZ1
    6.     dc.l Col_LZ2
    7.     dc.l Col_LZ3
    8.     dc.l Col_LZ4
    9.     dc.l Col_MZ1
    10.     dc.l Col_MZ2
    11.     dc.l Col_MZ3
    12.     dc.l Col_MZ4
    13.     dc.l Col_SLZ1
    14.     dc.l Col_SLZ2
    15.     dc.l Col_SLZ3
    16.     dc.l Col_SLZ4
    17.     dc.l Col_SYZ1
    18.     dc.l Col_SYZ2
    19.     dc.l Col_SYZ3
    20.     dc.l Col_SYZ4
    21.     dc.l Col_SBZ1
    22.     dc.l Col_SBZ2
    23.     dc.l Col_SBZ3
    24.     dc.l Col_SBZ4
    The ending zone ($06) is loaded separately, so at End_LoadData: replace Col_GHZ with Col_GHZ1 or Col_Ending. Obviously new entries will have to be create, so copy-paste all the collision data and add a number at the end; SonLVL INIs will also have to be edited to reflect the new data.

    Now, I know some of you will probably be using MarkeyJester's Two-Eight, so replace ColIndexLoad: with this:
    Code (Text):
    1. ; ---------------------------------------------------------------------------
    2. ; Collision index loading subroutine
    3. ; ---------------------------------------------------------------------------
    4.  
    5. ; ||||||||||||||| S U B    R O U T    I N E |||||||||||||||||||||||||||||||||||||||
    6.  
    7.  
    8. ColIndexLoad:                ; XREF: Level
    9.         move.w    ($FFFFFE10).w,d0
    10.         lsl.b    #6,d0
    11.         lsr.w    #3,d0                    ; MJ: multiply by 8 not 4
    12.         move.l    ColPointers(pc,d0.w),($FFFFFFD0).w    ; MJ: get first collision set
    13.         add.w    #4,d0                    ; MJ: increase to next location
    14.         move.l    ColPointers(pc,d0.w),($FFFFFFD4).w    ; MJ: get second collision set
    15.         rts
    16. ; End of function ColIndexLoad
    And Collision index pointers.asm with this:
    Code (Text):
    1. ; ---------------------------------------------------------------------------
    2. ; Collision index pointers
    3. ; ---------------------------------------------------------------------------
    4.     dc.l Col_GHZ1_1
    5.     dc.l Col_GHZ1_2
    6.     dc.l Col_GHZ2_1
    7.     dc.l Col_GHZ2_2
    8.     dc.l Col_GHZ3_1
    9.     dc.l Col_GHZ3_2
    10.     dc.l Col_GHZ4_1
    11.     dc.l Col_GHZ4_2
    12.     dc.l Col_LZ1_1
    13.     dc.l Col_LZ1_2
    14.     dc.l Col_LZ2_1
    15.     dc.l Col_LZ2_2
    16.     dc.l Col_LZ3_1
    17.     dc.l Col_LZ3_2
    18.     dc.l Col_LZ4_1
    19.     dc.l Col_LZ4_2
    20.     dc.l Col_MZ1_1
    21.     dc.l Col_MZ1_2
    22.     dc.l Col_MZ2_1
    23.     dc.l Col_MZ2_2
    24.     dc.l Col_MZ3_1
    25.     dc.l Col_MZ3_2
    26.     dc.l Col_MZ4_1
    27.     dc.l Col_MZ4_2
    28.     dc.l Col_SLZ1_1
    29.     dc.l Col_SLZ1_2
    30.     dc.l Col_SLZ2_1
    31.     dc.l Col_SLZ2_2
    32.     dc.l Col_SLZ3_1
    33.     dc.l Col_SLZ3_2
    34.     dc.l Col_SLZ4_1
    35.     dc.l Col_SLZ4_2
    36.     dc.l Col_SYZ1_1
    37.     dc.l Col_SYZ1_2
    38.     dc.l Col_SYZ2_1
    39.     dc.l Col_SYZ2_2
    40.     dc.l Col_SYZ3_1
    41.     dc.l Col_SYZ3_2
    42.     dc.l Col_SYZ4_1
    43.     dc.l Col_SYZ4_2
    44.     dc.l Col_SBZ1_1
    45.     dc.l Col_SBZ1_2
    46.     dc.l Col_SBZ2_1
    47.     dc.l Col_SBZ2_2
    48.     dc.l Col_SBZ3_1
    49.     dc.l Col_SBZ3_2
    50.     dc.l Col_SBZ4_1
    51.     dc.l Col_SBZ4_2
    Two-Eight combines both collision sets into the same table to save space, so our calculations had to be slightly altered.

    And there you go!

    EDIT: Added support for MarkeyJester's Project Sonic 1: Two-Eight.
     
    Last edited: Sep 4, 2020
  2. Lostgame

    Lostgame

    producer/turnablist. homebrew dev. cosplayer. Oldbie
    4,134
    58
    28
    Toronto, ON
    The O.I.C.
    So, sorry; I've seen this, as well as your 'dynamic tiles' system on the hacking guide, could you explain a little bit more about what it does / how it works? Sorry for not understanding the best. :3
     
  3. In Sonic 1 reading FFFFFE10 as a byte means per zone, as a word it means per act; changing the move.b ($FFFFFE10).w,d0 to a word isn't enough and thusly some changes had to be done.
     
  4. Now I just need to create a version compatible with MarkeyJester's Project: Sonic 128.