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): ; =========================================================================== ; --------------------------------------------------------------------------- ; Object 0F - Mappings test? ; --------------------------------------------------------------------------- Obj0F: moveq #0,d0 move.b routine(a0),d0 move.w Obj0F_Index(pc,d0.w),d1 jsr Obj0F_Index(pc,d1.w) bra.w DisplaySprite ; =========================================================================== Obj0F_Index: dc.w loc_B416-Obj0F_Index dc.w loc_B438-Obj0F_Index dc.w loc_B438-Obj0F_Index ; =========================================================================== loc_B416: addq.b #2,routine(a0) move.w #$90,8(a0) move.w #$90,$A(a0) move.l #Map_Obj0F,4(a0) move.w #$680,2(a0) bsr.w Adjust2PArtPointer loc_B438: move.b ($FFFFF605).w,d0 btst #5,d0 ; has C been pressed? beq.s loc_B44C ; if not, branch addq.b #1,$1A(a0) ; increment mappings andi.b #$F,$1A(a0) ; if above $F, reset loc_B44C: btst #4,d0 ; has B been pressed? beq.s locret_B458 ; if not, branch bchg #0,($FFFFFFE9).w ; set unused variable... which crashes the game? locret_B458: 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.
It might have something to do with entering cheats. In Sonic 1, FFE6/FFE7 counts the number of times C is pressed.
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): ; loc_B3D0: Obj0E_Display: bra.w DisplaySprite ; =========================================================================== ; leftovers from Sonic 1, moves Sonic up from underneath the banner ; Obj0E_Countdown: subq.b #1,$1F(a0) bpl.s locret_B3E2 addq.b #2,routine(a0) bra.w DisplaySprite ; =========================================================================== locret_B3E2: rts ; =========================================================================== ; loc_B3E4: Obj0E_Move: subi.w #8,$A(a0) cmpi.w #$96,$A(a0) bne.s Obj0E_Display2 addq.b #2,routine(a0) ; loc_B3F6: Obj0E_Display2: bra.w DisplaySprite ; =========================================================================== ; loc_B3FA: Obj0E_Display3: 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).
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): DynArtCue_Index: dc.w Dynamic_NullGHZ-DynArtCue_Index,AnimCue_EHZ-DynArtCue_Index dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index dc.w Dynamic_Normal-DynArtCue_Index,AnimCue_EHZ-DynArtCue_Index dc.w Dynamic_Normal-DynArtCue_Index,AnimCue_HPZ-DynArtCue_Index dc.w Dynamic_Normal-DynArtCue_Index,AnimCue_EHZ-DynArtCue_Index dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index dc.w Dynamic_Normal-DynArtCue_Index,AnimCue_HPZ-DynArtCue_Index dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index dc.w Dynamic_Null-DynArtCue_Index,AnimCue_CPZ-DynArtCue_Index Code (Text): AnimPatMaps: dc.w APM_GHZ-AnimPatMaps dc.w APM_LZ-AnimPatMaps dc.w APM_CPZ-AnimPatMaps dc.w APM_GHZ-AnimPatMaps dc.w APM_HPZ-AnimPatMaps dc.w APM_GHZ-AnimPatMaps dc.w APM_LZ-AnimPatMaps dc.w APM_LZ-AnimPatMaps dc.w APM_HPZ-AnimPatMaps dc.w APM_LZ-AnimPatMaps dc.w APM_LZ-AnimPatMaps dc.w APM_LZ-AnimPatMaps dc.w APM_LZ-AnimPatMaps dc.w APM_CPZ-AnimPatMaps dc.w APM_LZ-AnimPatMaps 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.
Definitely so: the debug mode source code snippet from the same prototype has these gems (relevant parts highlighted in bold by me): Code (Text): edit3tbl: ;zone0d dc.w 07 dcblw ring_act,ringpat,$26bc,0,$00 ;01: dcblw item_act,itempat,$0680,0,$00 ;02: dcblw sjump_act,sjumppat,$04a8,0,$00 ;03: dcblw colichg_act,colichgpat,$07bc,0,$00 ;04: dcblw kaiten_act,kaitenpat,$e000,0,$00 ;05: dcblw prodai_act,prodaipat,$e418,0,$00 ;06: dcblw buranko_act,buranko0dpat,$2418,0,$08 ;07: edit4tbl: ;zone00 dc.w 18 dcblw ring_act,ringpat,$26bc,0,$00 ;1: dcblw item_act,itempat,$0680,0,$00 ;2: dcblw save_act,savepat,$047c,0,$01 ;3: dcblw colichg_act,colichgpat,$26bc,0,$00 ;6: dcblw taki_act,takipat,$23ae,0,$00 ;7: dcblw taki_act,takipat,$23ae,3,$02 ;7: dcblw shima_act,dai00pat,$4000,0,$01 ;8: dcblw shima_act,dai00pat,$4000,1,$0a ;8: dcblw toge_act,togepat,$2434,0,$00 ;10: dcblw sisoo_act,sisoopat,$03ce,0,$00 ;9: dcblw sjump_act,banepat,$045c,0,$80 ;3: banev dcblw sjump_act,banepat,$0470,3,$90 ;3: baneh dcblw sjump_act,banepat,$045c,6,$a0 ;3: banevr dcblw sjump_act,banepat,$043c,7,$30 ;3: bane45 dcblw sjump_act,banepat,$043c,10,$40 ;3: bane45r dcblw wasp_act,wasppat,$03e6,0,$00 ;25 "" "" dcblw snail_act,snailpat,$0402,0,$00 ;25 "" "" dcblw wfish2_act,wfish2pat,$041c,0,$00 ;21 "" "" dcblw redz_act,redzpat,$0500,0,$00 ;20: will change dcblw bfish_act,bfishpat,$2530,0,$00 ;21 "" "" dcblw seahorse_act,horsepat,$2570,0,$00 ;22 "" "" dcblw skyhorse_act,horsepat,$2570,0,$00 ;23 "" "" dcblw stego_act,stegopat,$23c4,0,$00 ;24 "" "" dcblw wasp_act,wasppat,$032c,0,$00 ;25 "" "" dcblw gator_act,gatorpat,$2300,0,$00 ;26 "" "" dcblw bbat_act,bbatpat,$2350,0,$00 ;27 "" "" dcblw oct_act,octpat,$238a,0,$00 ;28 "" "" edit5tbl: edit6tbl: edit7tbl: ;zone08 dc.w 15 dcblw ring_act,ringpat,$26bc,0,$00 ;1: dcblw item_act,itempat,$0680,0,$00 ;2: dcblw bgspr_act,frntlitpat,$e485,3,$21 ;3: dcblw wfall_act,wfallpat,$e415,4,$04 ;4: dcblw break_act,pltfrmpat,$4475,0,$00 ;5: dcblw colichg_act,colichgpat,$26bc,0,$00 ;6: dcblw redz_act,redzpat,$0500,0,$00 ;20: will change dcblw bfish_act,bfishpat,$2530,0,$00 ;21 "" "" dcblw seahorse_act,horsepat,$2570,0,$00 ;22 "" "" dcblw skyhorse_act,horsepat,$2570,0,$00 ;23 "" "" dcblw stego_act,stegopat,$23c4,0,$00 ;24 "" "" dcblw wasp_act,wasppat,$032c,0,$00 ;25 "" "" dcblw gator_act,gatorpat,$2300,0,$00 ;26 "" "" dcblw bbat_act,bbatpat,$2350,0,$00 ;27 "" "" 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.
Indeed; in fact, the lack of the Death Egg's entry suggests this build was made around the time as the time travel maps: