Monday, January 8, 2018

The unused surfboard intro

In S3A only, if we go through the debug reel for Angel Island Zone 1, we eventually run across an unusual sprite, which when placed spawns the object seen below: a surfboarding Sonic that hovers around the player's position.


One thing which is immediately apparent about this object, is that much like the Flying Battery Zone monkey bar sprites before them, the surfboarding sprites are an almost perfect match for the standing sprite from Sonic 2:


When this object is spawned through debug mode, its subtype is always set to a non-zero value. And since it shares its VRAM address with the Sonic object, it corrupts Sonic's appearance as soon as it spawns.

However, when a subtype of 0 is supplied, the object actually turns Sonic invisible by setting his mapping frame to zero and disables his movement and animation routines by setting bits 0 and 1 of his object_control attribute:
Obj_SurfboardIntro:
    ...
    tst.b   $2C(a0)
    bne.s   loc_20B78
    lea     (Player_1).w,a1
    move.b  #0,$22(a1)
    move.b  #3,$2E(a1)

loc_20B78:
    ...
So what's going on? It turns out that underneath its surface, this object contains code for an alternate intro sequence to Angel Island Zone 1. The presence of Sonic 2 sprites suggests that this sequence was the stage's original intro, before the plane intro seen in the final game was implemented.

We can restore the surfboard intro by simply changing which intro object is spawned at the start of the level:
SpawnLevelMainSprites:                          SpawnLevelMainSprites:
    ...                                             ...
    cmpi.w  #0,(Current_zone_and_act).w             cmpi.w  #0,(Current_zone_and_act).w
    bne.s   loc_4DFE                                bne.s   loc_4DFE
    cmpi.w  #2,(Player_mode).w                      cmpi.w  #2,(Player_mode).w
    beq.s   locret_4DFC                             beq.s   locret_4DFC
    move.l  #Obj_PlaneIntro,($FFFFB172).w           move.l  #Obj_SurfboardIntro,($FFFFB172).w
    clr.b   (Level_started_flag).w                  clr.b   (Level_started_flag).w
    rts                                             rts
Since we're going to make a lot of modifications to the game this time around, I'll put any relevant PAR codes alongside their respective snippets. Here are the codes for the above change:
004DF0:0002
004DF2:0B0E
That alone restores most of the scrapped intro, but there are still a bunch of rough spots. For instance, although the big waves have somehow fixed themselves, Sonic still has a splash of garbage trailing behind him, and as he jumps off the surfboard, it too turns into a garbled mess. This is because the graphics for these objects have not been loaded.


As part of the setup for his intro sequence, when Sonic first starts Angel Island Zone 1, the game loads PLC $A instead of the regular AIZ1 PLC. Just by looking at it, though, we can easily spot the problem: when the intro was reworked, the graphics for the surfboard and its splash were removed from the PLC:
PLC_0A: dc.w 0
        dc.l ArtNem_AIZIntroSprites
        dc.w $7A20
Unfortunately, there's no longer any room to add those graphics back to the PLC without stepping over the regular AIZ1 PLC. Fortunately however, PLC 0 is completely unused, so we can repurpose it for our needs:
PLC_00: dc.w 3                                  PLC_00: dc.w 2
        dc.l ArtNem_SonicLifeIcon                       dc.l ArtNem_SurfboardSplash
        dc.w $FA80                                      dc.w $A520
        dc.l ArtNem_Ring                                dc.l ArtNem_AIZIntroSprites
        dc.w $D780                                      dc.w $7A20
        dc.l ArtNem_EnemyPts                            dc.l ArtNem_Surfboard
        dc.w $BC80                                      dc.w $B0A0
        dc.l ArtNem_Monitors                            dc.l ArtNem_Monitors
        dc.w $9880                                      dc.w $9880
Below are the PAR codes for these changes. My apologies.
05B084:0002
05B086:0014
05B088:86E0
05B08A:A520
05B08C:0014
05B08E:81A0
05B090:7A20
05B092:0014
05B094:8978
05B096:B0A0
All we have to do now is make the intro code load PLC 0 instead of PLC $A:
loc_4756:                                       loc_4756:
    bsr.w   LevelLoad_ActiveCharacter               bsr.w   LevelLoad_ActiveCharacter
    tst.b   (Last_star_post_hit).w                  tst.b   (Last_star_post_hit).w
    bne.w   loc_4782                                bne.w   loc_4782
    cmpi.w  #0,(Current_zone_and_act).w             cmpi.w  #0,(Current_zone_and_act).w
    bne.s   loc_4782                                bne.s   loc_4782
    cmpi.w  #2,(Player_mode).w                      cmpi.w  #2,(Player_mode).w
    beq.s   loc_4782                                beq.s   loc_4782
    moveq   #1,d0                                   moveq   #1,d0
    jsr     (Load_PLC_2).l                          jsr     (Load_PLC_2).l
    moveq   #$A,d0                                  moveq   #0,d0
    bsr.w   Load_PLC                                bsr.w   Load_PLC
    bra.s   loc_479A                                bra.s   loc_479A
Which translates to the following PAR code:
00477A:7000
Should look mighty slick now, but we still have an additional issue: since the title card never comes down, the level gets stuck in this weird state where there's no HUD, rings are invisible, and most other objects appear as a garbled mess:


To fix this, we can simply replace the surfboard intro object's final call to the Sprite_OnScreen_Test function with a call to the last routine of the cutscene Knuckles object, which fixes everything for free.
loc_20D38:                                      loc_20D38:
    jmp     (Sprite_OnScreen_Test).l                jmp     (loc_448B0).l
Doing so gives us our final two PAR codes:
020D3A:0004
020D3C:48B0
That should about cover it. Let's finally take a look at our fully-restored surfboard intro sequence:


I know, it's not perfect. Since the game doesn't wait for the Nemesis queue to be empty before starting the level, the big waves still appear garbled for a while. However, fixing this would require much deeper changes to the game's code, the likes of which are beyond the scope of simple PAR codes.

12 comments:

  1. Do you have your own Sonic 3 disassembly?

    ReplyDelete
    Replies
    1. I was going to ask the same question on this very post, lol! Apparently, Sonic Retro did not fork over an S3A disassembly, probably because it would be more interesting to have the S(3)K disassembly.

      Delete
    2. Wow, what a coincidence! Too bad the S3K disassembly is basically a S&K disassembly with only the required Sonic 3 data.

      Delete
    3. I have an incomplete disassembly which I work on bit by bit whenever there's something I need to look up. I'll probably release it eventually.

      Delete
  2. By chance, is there a reason why the game doesn't wait for the Nemesis queue to be clear before starting a level? Is it just to minimize load time?

    ReplyDelete
    Replies
    1. Probably. It is not immediately apparent to me why Sonic 3 uses both Nemesis queue and KosinskiM compression; you would think they'd pick one or the other. But even within a single level, the graphics for some enemies are stored in Nem format, while others are in KosM format.

      Delete
  3. How would I go about getting the graphics to work in S3K?
    Everything works but the graphics (they're a garbled mess).

    ReplyDelete
    Replies
    1. oh wait, I didn't realise that the art had a dummy reference that I missed in the version of the S3K disassembly that I have

      Delete
  4. Has this intro been implemented as a choice in "Sonic 3 Complete?"

    ReplyDelete
  5. It should have been; such a choice is welcome in Sonic 3 Complete.

    ReplyDelete
  6. I just thought of something; in the prototype of Sonic 3, there is an unusual Knuckles sprite, giving Sonic the "come hither". Touch up _that_ sprite to match Sonic 3 style,
    similarly redo Sonic's sprites to match, and put them together. Wouldn't THAT look better?

    ReplyDelete
  7. Hi there,

    Thank you so much for the post you do and also I like your post, are you looking for Buy jet board in the whole USA? We are providing Contact us for buying electric surfboards, Buy electric surfboard, Water jet board, Electric jet water board, Buy jet surf power board, Buy jet board, Buy jet surf power board, Where to buy a jet board, Jet water board, Water powered jet board, Electric jet board, Electric jet boards, jet board electric, electric jet body board for sale, electric jet water board, jet surf boards, jet surf power board for sale, Buy Carve Phantom, Buy Carve Phantom B Online, Buy Carve Surfboard, Buy Carve Tarifa B Online, Buy Freeride Board, Buy Freeride Element B Online, Buy Freeride Urban Board, Buy Freeride Urban rebel Online, Carve Tarifa, Freeride Element, Freeride Urban Rebel, Freeride X-Sport, Freeride Element B , Buy Freeride Board, Buy Freeride Urban Board, Buy X-sport board Online, Buy Charger Speed EU Online, Buy Charger Speed US Online, Buy Charger Standard EU Online, Buy Charger Speed US Online, Buy Battery Extended Range Online, Battery Extended Range, Battery Standard, Buy Battery Standard Online, in the world with the well price and our services are very fast.

    Click here href=" https://jetboardsupplier.com/product-category/batteries/"> title=” Batteries Archives - Jet Board Supplier”

    MORE DETAILS......
    Contact Us:
    WhatsApp us at: +1 (813) 421-0561
    Email: officialjetboard@gmail.com

    ReplyDelete