don't click here

ASM Sonic 3 & Knuckles Hacking

Discussion in 'Engineering & Reverse Engineering' started by Alex Field, Aug 29, 2021.

  1. "Because hackers can't avoid this game forever." - Alex Field, 2021

    Restore Full Super Sonic Palette Cycle:
    This first one is actually related somewhat to a bug in Sonic the Hedgehog 2.

    Specifically, hackers discovered awhile back that the palette cycle for Super Sonic is actually a lot smoother than what is seen in-game, having a proper loop instead of abruptly cutting:



    Well, as it turns out, this is actually caused by a minor logic error; at "SuperHyper_PalCycle_SuperSonic", you'll see this piece of code.
    Code (Text):
    1.         ; increment palette frame and update Sonic's palette
    2.         lea    (PalCycle_SuperSonic).l,a0
    3.         move.w    (Palette_frame).w,d0
    4.         addq.w    #6,(Palette_frame).w    ; next frame
    5.         cmpi.w    #$36,(Palette_frame).w    ; is it the last frame?
    6.         blo.s    loc_3898        ; <-- if not, branch
    7.         move.w    #$24,(Palette_frame).w    ; reset frame counter (Super Sonic's normal palette cycle starts at $24. Everything before that is for the palette fade)
    The problem is that the game is using 'blo' (branch on lower) instead of 'bls' (branch on lower or equal to), which causes it to miss the last frame of the palette cycle.

    Now that you're aware of the problem, the fix is quite simple, just change it to a 'bls'; keep in mind this also has to be changed at "loc_679D2" (the AIZ1 introduction).

    Sonic 3 Alone Level Select Code in Sonic & Knuckles:
    It's well-known at this point that the Sonic 3 Alone level select code is notoriously hard to input, but did you know it's in Sonic 3 & Knuckles too?

    Indeed! By searching up "S3_Level_Select_Code" in sonic3k.asm, you can see the original coding to handle the... code, with the only modification being a return command; even more interesting, it is not only does the Sonic 3 & Knuckles title screen branch to it, but so does the Sonic & Knuckles title screen.

    Humorously, the way the branch was handled in the Sonic 3 & Knuckles title screen makes it so that it can be inputted after the title screen pops-up; the only prototype this was useful in was Sonic & Knuckles 0608, and even then that was only via lock-on.
  2. Clownacy


    Tech Member
    its title doesn't really make it clear, but this type of thread already exists for Sonic 3 & Knuckles:

    It's a shame that threads like these get buried considering all the neat stuff in them. Aside from having these threads pinned, the only other solution I can think of is to put these fixes on the wiki instead of the forum.
    Last edited: Aug 29, 2021
  3. JcFerggy


    Do you want to taco 'bout it? Member
    Nova Scotia, Canada
    GoldenEye: Source, Other Stuff
    Having these sort of fixes on the wiki would be the ideal solution for easier reference in the future, but more onto that; I'm surprised that a bugfix project has never happened over the communities 20 year history.

    I realize this thread isn't the right place for such a conversation, but occasionally I'll come across articles online talking about fan improvement hacks like the SA-1 improvement hacks for certain SNES games, or DX colorized hacks of original Game Boy games, and I wonder why the Sonic community only comparable example is Sonic 3D Blast: Directors Cut? I suppose the discussion of the recommend way to play Sonic 1, 2, CD, and 3K can already summarized as "The mobile ports" and "Sonic 3 AIR". I'm not asking for a Sonic 1 SIR or Sonic 2 WIR equivalent, but I think a hack that compiles all the bug and slow down fixes, while keeping the game experience fairly vanilla would be appreciated by the greater rom hacking community. Tails and Knuckles can be ported if desired (spindash too), as they are as the original trio, but that's the most I'd want to stray from the originals. Other hacks like Sonic Classic Heroes fill that void for now, but a dedicated project to preserving the originals would be neat.
  4. Clownacy


    Tech Member
    If it helps, I did something like that for Sonic 2.
  5. MainMemory


    Kate the Wolf Tech Member
    The problem is, "Sonic 2 but there's no bugs" isn't really exciting by itself. Also, Sonic 3D Blast Director's Cut doesn't really count, that's the original developer working with the source code, not the community.

    Also, you're ignoring all the stuff that's been done for 3D games, SADX and SA2 have tons of mods that fix things and add improvements, Sonic Riders DX has been making the rounds at SAGE, and there's certainly more that I'm not thinking of.
  6. I agree; sure, some hacks (Sonic 3 Unlocked and Sonic 2: TRoDE) do include a lot of bug fixes, but they also take a lot of liberties with their source material.
  7. Black Squirrel

    Black Squirrel

    bed 'n' breakfast Wiki Sysop
    Northumberland, UK
    Wiki and Minnie's Runaway Railway
    In a weird sense I'm almost less bothered about "fixing" the bugs as documenting them:

    Sonic the Hedgehog 3/Bugs
    Sonic & Knuckles/Bugs
    Sonic the Hedgehog 3 & Knuckles/Bugs

    Not that I'm against an all-encompassing "fan revision" (although Sonic 3: AIR probably covers most issues), but it's nice to know what's wrong, so people can come up with their own fixes.

    Because yes, things do get lost in the forums.
  8. Nik Pi

    Nik Pi

    Sonic 2: Archives
    Here we go...
    Text editing:
    And let's talk about..
    Restoring Big arm (beginning)
    Firstly, find line loc_72B46:

    Code (Text):
    1. loc_72B46:
    2.         subq.w    #1,$2E(a0)
    3.         bpl.s    locret_72B94
    4.         lea    (Player_1).w,a1
    5.         btst    #7,$2A(a1)
    6.         bne.s    locret_72B94
    7.         btst    #1,$2A(a1)
    8.         bne.s    locret_72B94
    9.         cmpi.b    #6,5(a1)
    10.         bhs.s    locret_72B94
    11.         move.l    #loc_72B96,(a0)
    12.         jsr    (Set_PlayerEndingPose).l
    13.         clr.b    (End_of_level_flag).w
    14.         jsr    (Create_New_Sprite).l
    15.         bne.s    loc_72B86
    16.         move.l    #Obj_LevelResults,(a1)
    18. loc_72B86:
    19.         jsr    (Create_New_Sprite).l
    20.         bne.s    locret_72B94
    21.         move.l    #loc_72CFA,(a1)
    23. locret_72B94:
    24.         rts
    And replace with this:

    Code (Text):
    1. loc_72B46:
    2.         bset    #5,$38(a0)
    3.         move.w    (Camera_X_pos).w,d2
    4.         addi.w    #$100,d2
    5.         move.w    d2,$10(a0)
    6.         move.w    d1,$14(a0)
    7.         bclr    #0,4(a0)
    8.         bclr    #7,$A(a0)
    9.         jsr    (Create_New_Sprite).l
    10.         bne.s    loc_72B86
    11.         move.l    #Obj_LBZ_FinalBoss2,(a1)
    12.         move.w    $10(a0),$10(a1)
    13.         move.w    $14(a0),$14(a1)
    14.         lea    (Player_1).w,a1
    15.         bset #0,character_id(a0)
    16.         jsr    (Restore_PlayerControl).l
    17.         lea    (Player_2).w,a1
    18.         move.l    #Obj_Song_Fade_Transition,(a1)
    19.         move.b    #mus_FinalBoss,$2C(a1)
    21. loc_72B86:
    22.         jmp    (Go_Delete_Sprite_2).l
    This is line, that calls, when Sonic/Tails wins in battle vs LBZ first boss. In changed line- you can see, that here is called Big arm object (LBZ_FinalBoss2), and calls final boss music

    Find this:

    Code (Text):
    1. loc_7473A:
    2.         tst.b    (_unkFAA8).w
    3.         bne.w    locret_74374
    4.         tst.b    (_unkFAA2).w
    5.         beq.w    locret_74374
    6.         move.l    #loc_74768,(a0)
    7.         jsr    sub_7302E(pc)
    8.         bclr    #7,$2A(a0)
    9.         jsr    (Restore_PlayerControl).l
    10.         clr.w    (Ctrl_1_logical).w
    11.         st    (Ctrl_1_locked).w
    And replace with this:

    Code (Text):
    1. loc_7473A:
    2.         tst.b    (_unkFAA8).w
    3.         bne.w    locret_74374
    4.         tst.b    (_unkFAA2).w
    5.         beq.w    locret_74374
    6.         cmpi.w    #0,(Player_mode).w
    7.         beq.s    loc_72B962
    8.         cmpi.w    #1,(Player_mode).w
    9.         beq.s    loc_72B962
    10.         cmpi.w    #2,(Player_mode).w
    11.         beq.s    loc_72B962
    12.         move.l    #loc_74768,(a0)
    13.         jsr    sub_7302E(pc)
    14.         bclr    #7,$2A(a0)
    15.         jsr    (Restore_PlayerControl).l
    16.         clr.w    (Ctrl_1_logical).w
    17.         st    (Ctrl_1_locked).w
    Here code calls checks for player mode (Sonic and Tails/Sonic A/Tails A, if yes- go to next ending, if no- go to knux ending)
    It's not perfect, but it works)
    After- put this:

    Code (Text):
    1. loc_72B962:
    2.         tst.b    (End_of_level_flag).w
    3.         beq.w    locret_72B02
    4.         move.l    #loc_72BBC,(a0)
    5.         jsr    (Obj_PlayLevelMusic).l
    6.         move.w    #$1F,$2E(a0)
    7.         lea    (PLC_BossExplosion).l,a1
    8.         jmp    (Load_PLC_Raw).l
    Here you can see calling PLCs of explosion, and playing level music.
    After this- copy here all code from loc_72BBC to word_72EE8
    And delete this code in another place, ofcourse ;)

    For beginning- it's all. But this have a bug: Tails is missing in this battle! And.. idk, how to fix it, lmao.
    Palette porting will be later, when I'll find time for it)