Prototype Obj0F in Sonic 2 Nick Arcade

Discussion in 'Engineering & Reverse Engineering' started by Alex Field, Nov 26, 2021.

Tags:
  1. Alex Field

    Alex Field

    シュート! カオス・エメラルド・ザが消えようとしている! Member
    138
    79
    28
    Downunda, Mobius
    Sonic the Hedgehog 2+, Sonic the Hedgehog 3+
    I am making this thread to bring attention to a strange oddity in the Nick Arcade Sonic 2 prototype, something that as far as I know, hasn't been documented elsewhere.

    0x0F is an object ID used for the title screen menu starting in August 21st, but here, it seems to be a sort of 'mappings test'; here's the code, commented for your convenience:
    Code (Text):
    1. ; ===========================================================================
    2. ; ---------------------------------------------------------------------------
    3. ; Object 0F - Mappings test?
    4. ; ---------------------------------------------------------------------------
    5.  
    6. Obj0F:
    7.         moveq    #0,d0
    8.         move.b    routine(a0),d0
    9.         move.w    Obj0F_Index(pc,d0.w),d1
    10.         jsr    Obj0F_Index(pc,d1.w)
    11.         bra.w    DisplaySprite
    12. ; ===========================================================================
    13. Obj0F_Index:    dc.w loc_B416-Obj0F_Index
    14.         dc.w loc_B438-Obj0F_Index
    15.         dc.w loc_B438-Obj0F_Index
    16. ; ===========================================================================
    17.  
    18. loc_B416:
    19.         addq.b    #2,routine(a0)
    20.         move.w    #$90,8(a0)
    21.         move.w    #$90,$A(a0)
    22.         move.l    #Map_Obj0F,4(a0)
    23.         move.w    #$680,2(a0)
    24.         bsr.w    Adjust2PArtPointer
    25.  
    26. loc_B438:
    27.         move.b    ($FFFFF605).w,d0
    28.         btst    #5,d0        ; has C been pressed?
    29.         beq.s    loc_B44C    ; if not, branch
    30.         addq.b    #1,$1A(a0)    ; increment mappings
    31.         andi.b    #$F,$1A(a0)    ; if above $F, reset
    32.  
    33. loc_B44C:
    34.         btst    #4,d0        ; has B been pressed?
    35.         beq.s    locret_B458    ; if not, branch
    36.         bchg    #0,($FFFFFFE9).w    ; set unused variable... which crashes the game?
    37.  
    38. locret_B458:
    39.         rts
    As you can see, pressing C increments the current mappings, until you reach $10, in which it sets to $00; meanwhile, pressing B (seemingly at least) crashes the game by setting variable $FFE9... a variable I'm pretty sure is not used.
     
  2. Hivebrain

    Hivebrain

    Administrator
    2,931
    67
    28
    53.4N, 1.5W
    HiveView
    It might have something to do with entering cheats. In Sonic 1, FFE6/FFE7 counts the number of times C is pressed.
     
    • Informative Informative x 2
    • List
  3. Alex Field

    Alex Field

    シュート! カオス・エメラルド・ザが消えようとしている! Member
    138
    79
    28
    Downunda, Mobius
    Sonic the Hedgehog 2+, Sonic the Hedgehog 3+
    Actually, eems like $FFE9 is actually the high-bit of the two-player flag.

    Also, turns out the code to move Sonic to above the emblem in Sonic 1 is still present, just unused:
    Code (Text):
    1. ; loc_B3D0:
    2. Obj0E_Display:
    3.         bra.w    DisplaySprite
    4. ; ===========================================================================
    5. ; leftovers from Sonic 1, moves Sonic up from underneath the banner
    6. ; Obj0E_Countdown:
    7.         subq.b    #1,$1F(a0)
    8.         bpl.s    locret_B3E2
    9.         addq.b    #2,routine(a0)
    10.         bra.w    DisplaySprite
    11. ; ===========================================================================
    12.  
    13. locret_B3E2:
    14.         rts
    15. ; ===========================================================================
    16. ; loc_B3E4:
    17. Obj0E_Move:
    18.         subi.w    #8,$A(a0)
    19.         cmpi.w    #$96,$A(a0)
    20.         bne.s    Obj0E_Display2
    21.         addq.b    #2,routine(a0)
    22. ; loc_B3F6:
    23. Obj0E_Display2:
    24.         bra.w    DisplaySprite
    25. ; ===========================================================================
    26. ; loc_B3FA:
    27. Obj0E_Display3:
    28.         bra.w    DisplaySprite
    You can get it to display in-game by using PAR codes 00B3D0:4E71 and 00B3D2:4E71, although it doesn't exactly work as intended since Sonic/Tails never stop moving up (since they spawn with a different Y position).
     
    Last edited: Nov 29, 2021
  4. Alex Field

    Alex Field

    シュート! カオス・エメラルド・ザが消えようとしている! Member
    138
    79
    28
    Downunda, Mobius
    Sonic the Hedgehog 2+, Sonic the Hedgehog 3+
    Double posting due to an interesting discovery; seems like even at this stage, developers were already shifting stage IDs around, as proven in with the animated stage tile and block indexes:
    Code (Text):
    1. DynArtCue_Index:
    2.         dc.w Dynamic_NullGHZ-DynArtCue_Index,AnimCue_EHZ-DynArtCue_Index
    3.         dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index
    4.         dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index
    5.         dc.w Dynamic_Normal-DynArtCue_Index,AnimCue_EHZ-DynArtCue_Index
    6.         dc.w Dynamic_Normal-DynArtCue_Index,AnimCue_HPZ-DynArtCue_Index
    7.         dc.w Dynamic_Normal-DynArtCue_Index,AnimCue_EHZ-DynArtCue_Index
    8.         dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index
    9.         dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index
    10.         dc.w Dynamic_Normal-DynArtCue_Index,AnimCue_HPZ-DynArtCue_Index
    11.         dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index
    12.         dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index
    13.         dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index
    14.         dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index
    15.         dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index
    16.         dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index
    17.         dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index
    Code (Text):
    1. AnimPatMaps:    dc.w APM_GHZ-AnimPatMaps
    2.         dc.w APM_LZ-AnimPatMaps
    3.         dc.w APM_CPZ-AnimPatMaps
    4.         dc.w APM_GHZ-AnimPatMaps
    5.         dc.w APM_HPZ-AnimPatMaps
    6.         dc.w APM_GHZ-AnimPatMaps
    7.         dc.w APM_LZ-AnimPatMaps
    8.         dc.w APM_LZ-AnimPatMaps
    9.         dc.w APM_HPZ-AnimPatMaps
    10.         dc.w APM_LZ-AnimPatMaps
    11.         dc.w APM_LZ-AnimPatMaps
    12.         dc.w APM_LZ-AnimPatMaps
    13.         dc.w APM_LZ-AnimPatMaps
    14.         dc.w APM_CPZ-AnimPatMaps
    15.         dc.w APM_LZ-AnimPatMaps
    16.         dc.w APM_LZ-AnimPatMaps
    (note: in the original disassembly, drx thought the latter was per-act; relabeled to make things less confusing)

    Not only does Hidden Palace get entries in $08, but Chemical Plant has an entry in the animated block index in $0D (which matches their IDs in the final). The only entries missing are for Death Egg/Sky Chase.
     
    • Informative Informative x 2
    • List
  5. Brainulator

    Brainulator

    Regular garden-variety member Member
    Definitely so: the debug mode source code snippet from the same prototype has these gems (relevant parts highlighted in bold by me):
    Code (Text):
    1. edit3tbl:
    2. ;zone0d
    3.     dc.w    07
    4.     dcblw    ring_act,ringpat,$26bc,0,$00        ;01:
    5.     dcblw    item_act,itempat,$0680,0,$00        ;02:
    6.     dcblw    sjump_act,sjumppat,$04a8,0,$00        ;03:
    7.     dcblw    colichg_act,colichgpat,$07bc,0,$00    ;04:
    8.     dcblw    kaiten_act,kaitenpat,$e000,0,$00    ;05:
    9.     dcblw    prodai_act,prodaipat,$e418,0,$00    ;06:
    10.     dcblw    buranko_act,buranko0dpat,$2418,0,$08    ;07:
    11.  
    12. edit4tbl:
    13. ;zone00
    14.     dc.w    18
    15.     dcblw    ring_act,ringpat,$26bc,0,$00        ;1:
    16.     dcblw    item_act,itempat,$0680,0,$00        ;2:
    17.     dcblw    save_act,savepat,$047c,0,$01        ;3:
    18.  
    19.     dcblw    colichg_act,colichgpat,$26bc,0,$00    ;6:
    20.     dcblw    taki_act,takipat,$23ae,0,$00        ;7:
    21.     dcblw    taki_act,takipat,$23ae,3,$02        ;7:
    22.     dcblw    shima_act,dai00pat,$4000,0,$01        ;8:
    23.     dcblw    shima_act,dai00pat,$4000,1,$0a        ;8:
    24.     dcblw    toge_act,togepat,$2434,0,$00        ;10:
    25.     dcblw    sisoo_act,sisoopat,$03ce,0,$00        ;9:
    26.  
    27.     dcblw    sjump_act,banepat,$045c,0,$80        ;3: banev
    28.     dcblw    sjump_act,banepat,$0470,3,$90        ;3: baneh
    29.     dcblw    sjump_act,banepat,$045c,6,$a0        ;3: banevr
    30.     dcblw    sjump_act,banepat,$043c,7,$30        ;3: bane45
    31.     dcblw    sjump_act,banepat,$043c,10,$40        ;3: bane45r
    32.  
    33.     dcblw    wasp_act,wasppat,$03e6,0,$00        ;25   ""    ""
    34.     dcblw    snail_act,snailpat,$0402,0,$00        ;25   ""    ""
    35.     dcblw    wfish2_act,wfish2pat,$041c,0,$00    ;21   ""    ""
    36.  
    37.  
    38.  
    39.     dcblw    redz_act,redzpat,$0500,0,$00        ;20: will change
    40.     dcblw    bfish_act,bfishpat,$2530,0,$00        ;21   ""    ""
    41.     dcblw    seahorse_act,horsepat,$2570,0,$00    ;22   ""    ""
    42.     dcblw    skyhorse_act,horsepat,$2570,0,$00    ;23   ""    ""
    43.     dcblw    stego_act,stegopat,$23c4,0,$00        ;24   ""    ""
    44.     dcblw    wasp_act,wasppat,$032c,0,$00        ;25   ""    ""
    45.     dcblw    gator_act,gatorpat,$2300,0,$00        ;26   ""    ""
    46.     dcblw    bbat_act,bbatpat,$2350,0,$00        ;27   ""    ""
    47.     dcblw    oct_act,octpat,$238a,0,$00        ;28   ""    ""
    48.  
    49. edit5tbl:
    50. edit6tbl:
    51. edit7tbl:
    52. ;zone08
    53.     dc.w    15
    54.     dcblw    ring_act,ringpat,$26bc,0,$00        ;1:
    55.     dcblw    item_act,itempat,$0680,0,$00        ;2:
    56.  
    57.     dcblw    bgspr_act,frntlitpat,$e485,3,$21    ;3:
    58.     dcblw    wfall_act,wfallpat,$e415,4,$04        ;4:
    59.     dcblw    break_act,pltfrmpat,$4475,0,$00        ;5:
    60.     dcblw    colichg_act,colichgpat,$26bc,0,$00    ;6:
    61.  
    62.     dcblw    redz_act,redzpat,$0500,0,$00        ;20: will change
    63.     dcblw    bfish_act,bfishpat,$2530,0,$00        ;21   ""    ""
    64.     dcblw    seahorse_act,horsepat,$2570,0,$00    ;22   ""    ""
    65.     dcblw    skyhorse_act,horsepat,$2570,0,$00    ;23   ""    ""
    66.     dcblw    stego_act,stegopat,$23c4,0,$00        ;24   ""    ""
    67.     dcblw    wasp_act,wasppat,$032c,0,$00        ;25   ""    ""
    68.     dcblw    gator_act,gatorpat,$2300,0,$00        ;26   ""    ""
    69.     dcblw    bbat_act,bbatpat,$2350,0,$00        ;27   ""    ""
    70.     dcblw    oct_act,octpat,$238a,0,$00        ;28   ""    ""
    While from a build that predates Nick Arcade (Scrap Brain/Hill Top has no actual list in this code, which would be at "edit6tbl"), the entries actually have labels referencing Emerald Hill as zone $00, Chemical Plant as zone $0D, and Hidden Palace as zone $08 - all consistent with their final internal order.

    This definitely seems like this level order dates back to Sonic 2's early days as a time-traveling adventure.
     
    • Informative Informative x 1
    • List
  6. Alex Field

    Alex Field

    シュート! カオス・エメラルド・ザが消えようとしている! Member
    138
    79
    28
    Downunda, Mobius
    Sonic the Hedgehog 2+, Sonic the Hedgehog 3+
    Indeed; in fact, the lack of the Death Egg's entry suggests this build was made around the time as the time travel maps:
    [​IMG]