Restore Surfboard Intro to Sonic 3 Alone
From Sonic Retro
Revision as of 12:57, 26 February 2019 by Inferno Gear (talk | contribs) (Created page with "''(Guide by Inferno Gear, based on: https://s3unlocked.blogspot.com/2018/01/the-unused-surfboard-intro.html, by Fred Bronze for his blog Sonic 3 Unlocked)...")
(Guide by Inferno Gear, based on: https://s3unlocked.blogspot.com/2018/01/the-unused-surfboard-intro.html, by Fred Bronze for his blog Sonic 3 Unlocked)
So, say you want to restore the surfboard intro to Sonic 3 Alone. You would have to manually hex edit an intact ROM of Sonic 3 Alone, which could be quite the pain! That is, until now! With Fred Bronze's new Sonic 3 Alone disassembly as part of the Sonic & Knuckles GitHub disassembly, you can now edit Sonic 3 Alone in regular ASM!
However, where would you begin to start modifying back in the Surfboard intro to be almost fully perfect? Well, that's what this guide is for!
If you search Obj_AIZSurfboardIntro:, you'll find this piece of code:
Obj_AIZSurfboardIntro:
move.l #Map_SurfboardIntro,$C(a0)
move.w #$100,8(a0)
move.b #$20,7(a0)
move.b #4,4(a0)
move.w #$680,$A(a0)
move.b #-1,(Player_prev_frame).w
move.l #Obj_AIZSurfboardIntro_Main,(a0)
move.w (Player_1+x_pos).w,$10(a0)
move.w (Player_1+y_pos).w,$14(a0)
subi.w #$20,$10(a0)
subi.w #$10,$14(a0)
move.w #0,$18(a0)
move.w #0,$1A(a0)
clr.w ($FFFFEEB6).w
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:
jsr (Create_New_Sprite3).l
bne.w Obj_AIZSurfboardIntro_Main
move.l #Obj_SurfboardSplash,(a1)
move.w a0,$30(a1)
Obj_AIZSurfboardIntro_Main:
tst.b $2C(a0)
bne.s loc_20BFC
lea (Player_1).w,a1
addi.w #8,$10(a1)
addi.w #8,$10(a0)
cmpi.w #$900,$10(a1)
bcs.s loc_20BFC
jsr (Create_New_Sprite3).l
bne.w loc_20BD0
move.l #Obj_Surfboard,(a1)
move.w $10(a0),$10(a1)
move.w $14(a0),$14(a1)
addi.w #$C,$14(a1)
move.w a0,$30(a1)
loc_20BD0:
move.w #$800,$18(a0)
move.w #-$400,$1A(a0)
move.l #Obj_AIZSurfboardIntro_Jump,(a0)
move.w #1,$20(a0)
subi.w #5,$10(a0)
move.b #7,$22(a0)
jsr (SurfboardIntro_LoadPLC).l
bra.s loc_20C00
; ---------------------------------------------------------------------------
loc_20BFC:
bsr.w SurfboardIntro_Move
loc_20C00:
jmp (Sprite_OnScreen_Test).l
; ---------------------------------------------------------------------------
Obj_AIZSurfboardIntro_Jump:
lea (Player_1).w,a1
addi.w #8,$10(a1)
jsr (MoveSprite2).l
addi.w #$20,$1A(a0)
moveq #1,d2
move.w $10(a0),d0
cmp.w $10(a1),d0
beq.s loc_20C30
blt.s loc_20C2C
neg.w d2
loc_20C2C:
add.w d2,$10(a0)
loc_20C30:
tst.w $1A(a0)
bmi.s loc_20C74
cmpi.w #$440,$14(a0)
bcs.s loc_20C74
move.w #$440,$14(a0)
move.w #0,$1A(a0)
move.w $10(a0),$10(a1)
move.w $14(a0),$14(a1)
move.w #1,$20(a1)
move.w #$800,$1C(a1)
move.w #$800,$18(a1)
move.w #0,$1A(a1)
move.l #Obj_AIZSurfboardIntro_Run,(a0)
loc_20C74:
lea (Ani_SurfboardIntro).l,a1
jsr (Animate_Sprite).l
jsr (SurfboardIntro_LoadPLC).l
jmp (Sprite_OnScreen_Test).l
; ---------------------------------------------------------------------------
Ani_SurfboardIntro:
include "General/Sprites/Sonic/Anim - Sonic Surfboard.asm"
; ---------------------------------------------------------------------------
Obj_AIZSurfboardIntro_Run:
movea.l a0,a3
lea (Player_1).w,a0
move.w #0,$1A(a0)
cmpi.w #$1170,$10(a0)
bcs.s loc_20CB6
cmpi.w #$1270,$10(a0)
bcc.s loc_20CB6
move.w #-$138,$1A(a0)
loc_20CB6:
jsr (MoveSprite2).l
cmpi.w #$13C0,$10(a0)
bcs.s loc_20CE2
move.b #0,$2E(a0)
move.l #Obj_AIZSurfboardIntro_Stop,(a3)
move.b #1,(Ctrl_1_locked).w
move.w #$400,(Ctrl_1_logical).w
move.w #$E,$2E(a3)
loc_20CE2:
jsr (Animate_Sonic).l
move.l a3,-(sp)
jsr (Sonic_Load_PLC).l
movea.l (sp)+,a0
addi.w #8,$10(a0)
move.b #0,$22(a0)
jmp (Sprite_OnScreen_Test).l
; ---------------------------------------------------------------------------
Obj_AIZSurfboardIntro_Stop:
subq.w #1,$2E(a0)
bpl.s loc_20D32
lea (Player_1).w,a1
move.w #0,$1C(a1)
move.w #0,$18(a1)
move.w #0,$1A(a1)
move.b #0,(Ctrl_1_locked).w
move.w #0,(Ctrl_1_logical).w
move.l #Obj_AIZSurfboardIntro_CheckDelete,(a0)
loc_20D32:
jmp (Sprite_OnScreen_Test).l
; ---------------------------------------------------------------------------
Obj_AIZSurfboardIntro_CheckDelete:
jmp (Sprite_OnScreen_Test).l
; =============== S U B R O U T I N E =======================================
SurfboardIntro_Move:
move.w #2,d1
move.w (Player_1+x_pos).w,d0
cmp.w $10(a0),d0
bcc.s loc_20D4E
neg.w d1
loc_20D4E:
add.w d1,$18(a0)
moveq #0,d2
lea (SurfboardIntro_DownFrames).l,a1
move.w #3,d1
move.w (Player_1+y_pos).w,d0
cmp.w $14(a0),d0
bcc.s loc_20D76
moveq #1,d2
lea (SurfboardIntro_UpFrames).l,a1
move.w #4,d1
neg.w d1
loc_20D76:
add.w d1,$1A(a0)
jsr (MoveSprite2).l
move.w $1A(a0),d0
tst.w d2
bne.s loc_20D8A
neg.w d0
loc_20D8A:
addi.w #$80,d0
cmpi.w #$100,d0
bcs.s loc_20D98
move.w #$100,d0
loc_20D98:
lsr.w #5,d0
move.b (a1,d0.w),d0
addq.b #1,d0
move.b d0,$22(a0)
jsr (SurfboardIntro_LoadPLC).l
subq.w #1,$2E(a0)
bpl.s locret_20DCA
move.w #5,$2E(a0)
jsr (Create_New_Sprite3).l
bne.w locret_20DCA
move.l #Obj_SurfboardWaves,(a1)
move.w a0,$30(a1)
locret_20DCA:
rts
; ---------------------------------------------------------------------------
SurfboardIntro_DownFrames:
dc.b 2, 1, 1, 0, 0, 0, 0, 1, 2, 2
SurfboardIntro_UpFrames:
dc.b 3, 4, 4, 4, 5, 5, 5, 4, 3, 3
; End of function SurfboardIntro_Move
; =============== S U B R O U T I N E =======================================
SurfboardIntro_LoadPLC:
moveq #0,d0
move.b $22(a0),d0
cmp.b (Player_prev_frame).w,d0
beq.s locret_20E32
move.b d0,(Player_prev_frame).w
lea (DPLC_SurfboardIntro).l,a2
add.w d0,d0
adda.w (a2,d0.w),a2
move.w (a2)+,d5
subq.w #1,d5
bmi.s locret_20E32
move.w #-$3000,d4
loc_20E06:
moveq #0,d1
move.w (a2)+,d1
move.w d1,d3
lsr.w #8,d3
andi.w #$F0,d3
addi.w #$10,d3
andi.w #$FFF,d1
lsl.l #5,d1
addi.l #ArtUnc_SurfboardIntro,d1
move.w d4,d2
add.w d3,d4
add.w d3,d4
jsr (Add_To_DMA_Queue).l
dbf d5,loc_20E06
locret_20E32:
rts
; End of function SurfboardIntro_LoadPLC
; ---------------------------------------------------------------------------
Map_SurfboardIntro:
include "General/Sprites/Sonic/Map - Sonic Surfboarding.asm"
DPLC_SurfboardIntro:
include "General/Sprites/Sonic/DPLC - Sonic Surfboarding.asm"
; ---------------------------------------------------------------------------
This is the main code for the Surfboard intro object, which is referenced in the debug list for Angel Island Zone. Let's rememeber Obj_AIZSurfboardIntro, it will be needed.
Now to add back in the surfboard as the object that loads for the intro. Go to SpawnLevelMainSprites, you should see this code:
SpawnLevelMainSprites:
move.l #Obj_Level_50B2,(Reserved_object_3).w
bsr.w SpawnLevelMainSprites_SpawnPlayers
bsr.w SpawnLevelMainSprites_SpawnPowerup
tst.b (Last_star_post_hit).w
bne.w locret_4EC6
tst.b (Special_bonus_entry_flag).w
loc_4DD2:
bne.w locret_4EC6
lea (Player_1).w,a1
lea (Player_2).w,a2
cmpi.w #0,(Current_zone_and_act).w
bne.s loc_4DFE
cmpi.w #2,(Player_mode).w
beq.s locret_4DFC
move.l #Obj_AIZPlaneIntro,($FFFFB172).w
clr.b (Level_started_flag).w
rts
I want you to look at this fragment.
cmpi.w #0,(Current_zone_and_act).w
bne.s loc_4DFE
cmpi.w #2,(Player_mode).w
beq.s locret_4DFC
move.l #Obj_AIZPlaneIntro,($FFFFB172).w
What this does is if the current Zone and Act ID isn't Angel Island, branch to loc_$4DFE. After that, it checks for Player Mode ID 2, which means it's checking if the player is Tails. If it is, it branches to locret_$4DFC. Finally, it adds Obj_AIZPlaneIntro to RAM Address $FFFFB172, which is used for reserved Object SSTs. It spawns the plane intro right there. Change the instance of #Obj_AIZPlaneIntro to Obj_AIZSurfboardIntro.
(WIP)