Restore the GHZ Ball from Sonic 1 Prototype

Discussion in 'Tutorials' started by Candy_TheCat, Feb 15, 2021.

Tags:
  1. Candy_TheCat

    Candy_TheCat CandyTehRat Member

    Joined:
    Jan 15, 2021
    Messages:
    29
    Location:
    Chemical Plant Zone
    Last time on February 15th of 2021 I posted a tutorial on how to quote on quote "restore" the GHZ ball. Back then, !!!I DID NOT KNOW WHAT I WAS DOING WHATSOEVER!!!

    So I decided to make a NEW thread and revisit the inaccuracies and mistakes I missed in my "tutorial".

    Github Diassmebly

    1: Importing the code from the prototype
    Now here's where we are gonna get our disassemblies out today. Firstly download the MDDC disassembly. It is mostly recommended considering in the inaccurate tutorial from months ago it targeted MDDC's.

    Now look for the code for Object ID 19. In MDDC it is included in the main text file sonic.asm. It will be labeled "ObjRollingBall" in MDDC. Now the code SHOULD look like this.

    Code:
    ObjRollingBall:
            moveq    #0,d0
            move.b    $24(a0),d0
            move.w    off_5C8E(pc,d0.w),d1
            jmp    off_5C8E(pc,d1.w)
    ; ---------------------------------------------------------------------------
    
    off_5C8E:    dc.w loc_5C98-off_5C8E, loc_5D2C-off_5C8E, loc_5D86-off_5C8E, loc_5E4A-off_5C8E, loc_5CEE-off_5C8E
    ; ---------------------------------------------------------------------------
    
    loc_5C98:
            move.b    #$18,$16(a0)
            move.b    #$C,$17(a0)
            bsr.w    ObjectFall
            jsr    ObjectHitFloor
            tst.w    d1
            bpl.s    locret_5CEC
            add.w    d1,$C(a0)
            move.w    #0,$12(a0)
            move.b    #8,$24(a0)
            move.l    #MapRollingBall,4(a0)
            move.w    #$43AA,2(a0)
            move.b    #4,1(a0)
            move.b    #3,$19(a0)
            move.b    #$18,$18(a0)
            move.b    #1,$1F(a0)
            bsr.w    sub_5DC8
    
    locret_5CEC:
            rts
    ; ---------------------------------------------------------------------------
    
    loc_5CEE:
            move.w    #$23,d1
            move.w    #$18,d2
            move.w    #$18,d3
            move.w    8(a0),d4
            bsr.w    sub_A2BC
            btst    #5,$22(a0)
            bne.s    loc_5D14
            move.w    (ObjectsList+8).w,d0
            sub.w    8(a0),d0
            bcs.s    loc_5D20
    
    loc_5D14:
            move.b    #2,$24(a0)
            move.w    #$80,$14(a0)
    
    loc_5D20:
            bsr.w    sub_5DC8
            bsr.w    ObjectDisplay
            bra.w    loc_5E2A
    ; ---------------------------------------------------------------------------
    
    loc_5D2C:
            btst    #1,$22(a0)
            bne.w    loc_5D86
            bsr.w    sub_5DC8
            bsr.w    sub_5E50
            bsr.w    ObjectMove
            move.w    #$23,d1
            move.w    #$18,d2
            move.w    #$18,d3
            move.w    8(a0),d4
            bsr.w    sub_A2BC
            jsr    ObjSonic_AnglePosition
            cmpi.w    #$20,8(a0)
            bcc.s    loc_5D70
            move.w    #$20,8(a0)
            move.w    #$400,$14(a0)
    
    loc_5D70:
            btst    #1,$22(a0)
            beq.s    loc_5D7E
            move.w    #$FC00,$12(a0)
    
    loc_5D7E:
            bsr.w    ObjectDisplay
            bra.w    loc_5E2A
    ; ---------------------------------------------------------------------------
    
    loc_5D86:
            bsr.w    sub_5DC8
            bsr.w    ObjectMove
            move.w    #$23,d1
            move.w    #$18,d2
            move.w    #$18,d3
            move.w    8(a0),d4
            bsr.w    sub_A2BC
            jsr    ObjSonic_Floor
            btst    #1,$22(a0)
            beq.s    loc_5DBE
            move.w    $12(a0),d0
            addi.w    #$28,d0
            move.w    d0,$12(a0)
            bra.s    loc_5DC0
    ; ---------------------------------------------------------------------------
    
    loc_5DBE:
            nop
    
    loc_5DC0:
            bsr.w    ObjectDisplay
            bra.w    loc_5E2A
    ; ---------------------------------------------------------------------------
    
    sub_5DC8:
            tst.b    $1A(a0)
            beq.s    loc_5DD6
            move.b    #0,$1A(a0)
            rts
    ; ---------------------------------------------------------------------------
    
    loc_5DD6:
            move.b    $14(a0),d0
            beq.s    loc_5E02
            bmi.s    loc_5E0A
            subq.b    #1,$1E(a0)
            bpl.s    loc_5E02
            neg.b    d0
            addq.b    #8,d0
            bcs.s    loc_5DEC
            moveq    #0,d0
    
    loc_5DEC:
            move.b    d0,$1E(a0)
            move.b    $1F(a0),d0
            addq.b    #1,d0
            cmpi.b    #4,d0
            bne.s    loc_5DFE
            moveq    #1,d0
    
    loc_5DFE:
            move.b    d0,$1F(a0)
    
    loc_5E02:
            move.b    $1F(a0),$1A(a0)
            rts
    ; ---------------------------------------------------------------------------
    
    loc_5E0A:
            subq.b    #1,$1E(a0)
            bpl.s    loc_5E02
            addq.b    #8,d0
            bcs.s    loc_5E16
            moveq    #0,d0
    
    loc_5E16:
            move.b    d0,$1E(a0)
            move.b    $1F(a0),d0
            subq.b    #1,d0
            bne.s    loc_5E24
            moveq    #3,d0
    
    loc_5E24:
            move.b    d0,$1F(a0)
            bra.s    loc_5E02
    ; ---------------------------------------------------------------------------
    
    loc_5E2A:
            move.w    8(a0),d0
            andi.w    #$FF80,d0
            move.w    (CameraX).w,d1
            subi.w    #$80,d1
            andi.w    #$FF80,d1
            sub.w    d1,d0
            cmpi.w    #$280,d0
            bhi.w    ObjectDelete
            rts
    ; ---------------------------------------------------------------------------
    
    loc_5E4A:
            bsr.w    ObjectDelete
            rts
    ; ---------------------------------------------------------------------------
    
    sub_5E50:
            move.b    $26(a0),d0
            bsr.w    GetSine
            move.w    d0,d2
            muls.w    #$38,d2
            asr.l    #8,d2
            add.w    d2,$14(a0)
            muls.w    $14(a0),d1
            asr.l    #8,d1
            move.w    d1,$10(a0)
            muls.w    $14(a0),d0
            asr.l    #8,d0
            move.w    d0,$12(a0)
            rts
    ; ---------------------------------------------------------------------------
            include "levels/GHZ/RollingBall/Sprite.map"
            even
    ; ---------------------------------------------------------------------------
    
    Now I know what you are thinking. "I can just put this in and call it a day!".

    Well...

    NOPE!

    This code features invalid code not used in the final, so we need to replace some code with the final versions.

    2: Changing prototype code
    DO NOT SKIP THIS PART! This is an important part, skipping this would lead to lots of errors.

    Now firstly, you may see the title "ObjRollingBall". Well in Github it is simply labeled "Obj19". Simply just replace the prototype title with "Obj19". So that is it right? Still no. There is more to replace.

    Here is the graphic code:


    Code:
            move.l    #MapRollingBall,4(a0)
    
            move.w    #$43AA,2(a0)
    In Github, there is no such thing as "MapRollingBall" whatsoever. We are gonna have to replace it with this.
    Code:
            move.l    #Map_GBall,obMap(a0)
            move.w    #$43AA,obGfx(a0)
    The second problem is a major part of the code, named sub_A2BC. This is an obvious prototype version of SolidObject. Replacing it to SpeedToPos is VERY unrecommended. If your looking for a more accurate ball, I recommend replacing it with SolidObject.

    Replace it with either, I really don't care. As long as your ball is moving and it makes you happy, that's good.

    Another major part is ObjectMove. This basically makes it move and what makes it roll. Now seen in MDDC, it is VERY similar to "BossMove", Something to make bosses move.

    BossToMove Path
    Scroll all the way to the bottom of your code, and copy and paste the BossMove code, replace the label "BossMove" with "ObjectMove", Simple.

    SpeedToPos Path
    In the comments, Painto pointed out ObjectMove is actually SpeedToPos. Replace ObjectMove w/ SpeedToPos.

    -------------------------------------------

    There is now something called ObjectFloorDistance. This is obviously Obj_FloorDist. Replace it with that.

    ObjSonic_AnglePosition? Basically Sonic_AnglePos. Replace it with that. Obj_SonicFloor? Leave Sonic_Floor exactly the way it is, though delete the "Obj" part. Now for "GetSine". Replace it with CalcSine. ObjectDisplay is DisplaySprite... ObjectDelete.. DeleteObject.. Blah blah blah i could do this all da- wait a second.. CAMERAX?! What is CameraX you ask? Its a flag in the final game Simply replace it with $FFFFF700. There's also ObjectList. Just delete that simply, or replace it with v_player.

    Delete this:
    Code:
    ; ---------------------------------------------------------------------------
            include "levels/GHZ/RollingBall/Sprite.map"
            even
    ; ---------------------------------------------------------------------------
    Or the build will have.. certain problems.

    3. Make those balls solid
    In case step 2 didn't work with the sub_A2BC part, use step 3.

    Can't be balls without it being SOLID!
    Put this code under all bsr.w SpeedToPos:

    Code:
    move.w   #$20,d1
    move.w   #$1B,d2
    move.w   #$18,d3
    bsr.w       SolidObject
    Oh yeah! We're done! Now build the game and.. wait an error of bsr.w MvSonicOnPlatform? Wait how can Github make an error of a code that's been in the game for 30 years? The answer is the bsr.w SolidObject. Don't delete the SolidObject. Go to "sub SolidObject" in your "_incObj" folder in your diassembly and replace bsr.w MvSonicOnPlatform with "jsr MvSonicOnPlatform".

    4. BUILD DAT GAME UP!

    Now your balls should be ready! Build the game up and.. wait a second is that..

    [​IMG]
    T-T...TWO BALLS? Apparently, when those balls are offscreen, another ball respawns. And it does NOT delete the previous ball.
    Here's a problem I cannot fix. If anyone knows how to fix this just let me know.

    EDIT: Something about three previous points in loc_5E2A causes this. Also I'd like to thank Painto for correcting me on some things, without them this revisited thread would be inaccurate again.





    HIVEBRAIN TUTORIAL COMMIN' SOON!

     
    Last edited: Dec 4, 2021
  2. Stdh

    Stdh Active Member Member

    Joined:
    Jan 11, 2021
    Messages:
    30
    Location:
    the netherlands
    thank you for this!
     
  3. Candy_TheCat

    Candy_TheCat CandyTehRat Member

    Joined:
    Jan 15, 2021
    Messages:
    29
    Location:
    Chemical Plant Zone
    No problem! However, if it says theres errors in sub SolidObject about the "bsr.w MvSonicOnPlatform", change bsr.w to jsr instead.

    Edit: set it to jsr not jmp
     
    Last edited: Feb 16, 2021
  4. Inferno

    Inferno Rom Hacker Member

    Joined:
    Oct 27, 2015
    Messages:
    132
    Location:
    Sky Base Zone, South Island
    Don't do this, that's not the right instruction for any distance branching and returning.

    Do jsr instead, jmp is for bra instructions.
     
  5. Matt

    Matt Active Member Member

    Joined:
    Jan 31, 2021
    Messages:
    47
    Location:
    Italy
    Thank you GottaGoFast. Now i can build my own Sonic 1 Beta Remake. :D
     
  6. TomTalker

    TomTalker Newcomer Prospect

    Joined:
    Feb 20, 2021
    Messages:
    10
    Location:
    Emerald Hill
    Thank you so much for this tutorial! I hope to see more working GHZ Prototype Balls in new hacks! ;P
     
  7. Matt

    Matt Active Member Member

    Joined:
    Jan 31, 2021
    Messages:
    47
    Location:
    Italy
    i've founded out that there are some "Undefined label" errors after running build.bat:
    Error : Symbol 'objecthitfloor' not defined
    Error : Symbol 'objectslist' not defined
    Error : Symbol 'objectdisplay' not defined
    Error : Symbol 'objsonic_angleposition' not defined
    Error : Symbol 'objsonic_floor' not defined
    Error : Symbol 'camerax' not defined
    Error : Symbol 'objectdelete' not defined

    so you need to replace:
    'objecthitfloor' with 'ObjFloorDist' , 'ObjFindFloor' or 'Sonic_Floor' (?) [in this case try both]
    'objectslist' with 'Object_Pointers'
    'objectdisplay' with 'DisplaySprite'
    'objsonic_angleposition' with 'Sonic_AnglePos'
    'objsonic_floor' with 'Sonic_Floor'
    'camerax' with (?) [seriously, i don't know how to replace this *facepalm*]
    'objectdelete' with 'DeleteObject'

    i hope this will be helpful! ;)
     
  8. Candy_TheCat

    Candy_TheCat CandyTehRat Member

    Joined:
    Jan 15, 2021
    Messages:
    29
    Location:
    Chemical Plant Zone
    CameraX is a old and unused label from the prototype, after updating the code because there was a few innacuracies I made with the ported ball code, I realised CameraX is its only flag in the final. The flag is $FFFFF700
     
    Last edited: Jun 15, 2021
    Matt likes this.
  9. Matt

    Matt Active Member Member

    Joined:
    Jan 31, 2021
    Messages:
    47
    Location:
    Italy
    ok, but if you can, change the code for making the ball work since i'd some stressful moments while i was redefining the early code for making it working on the final version. thanks!
     
  10. Candy_TheCat

    Candy_TheCat CandyTehRat Member

    Joined:
    Jan 15, 2021
    Messages:
    29
    Location:
    Chemical Plant Zone
    Boutta revisit ths lol
     
  11. Candy_TheCat

    Candy_TheCat CandyTehRat Member

    Joined:
    Jan 15, 2021
    Messages:
    29
    Location:
    Chemical Plant Zone
    made a new thing for the tutorial, enjoy
     
    Last edited: Dec 4, 2021
    JGamer2151, ProjectFM and Filter like this.
  12. Painto

    Painto Arthurus Paintus Erinaceus Member

    Joined:
    Mar 24, 2014
    Messages:
    321
    Location:
    Lublin, Poland
    I'd like to adress few things I noticed:

    Actually judging by setup itself (values for d1-d4) it seems to be a call for SolidObject, not SpeedToPos. This also makes step 3 redundant.

    Even simpler, it's actually SpeedToPos.

    I personally don't see any reason for deletion for this one, and while I didn't looked into the proto disasm, I can safely assume from similar objects that "ObjectList" is "v_player"/$FFFFD000.

    Also:
    Code for that is in the object (loc_5E2A), so maybe it has something to do with three previous points.
     
  13. Candy_TheCat

    Candy_TheCat CandyTehRat Member

    Joined:
    Jan 15, 2021
    Messages:
    29
    Location:
    Chemical Plant Zone
    Ill re-edit the thread I made in a sec
     
  14. D.A. Garden

    D.A. Garden Sonic CD's Sound Test Member

    Joined:
    Aug 6, 2009
    Messages:
    582
    Location:
    England
    I have merged the two threads together. There was no need to create a separate one, as the content in the second thread was a progression of the first thread.
     
  15. Candy_TheCat

    Candy_TheCat CandyTehRat Member

    Joined:
    Jan 15, 2021
    Messages:
    29
    Location:
    Chemical Plant Zone
    Thank you.

    Edit: replaced the comment and copy and pasted the revised tutorial onto the main thread.
     
  16. Hame

    Hame Peepee Poopoo Member

    Joined:
    Jan 12, 2021
    Messages:
    51
    Location:
    Spain
    so that the ball does not disappear you must remove the delete object from loc_5E2A and loc_5E4A, and that 2 balls do not appear simply in the level editor you must activate this:
     

    Attached Files:

    Last edited: May 29, 2023
  17. Hame

    Hame Peepee Poopoo Member

    Joined:
    Jan 12, 2021
    Messages:
    51
    Location:
    Spain
    edit: throw this away, I accidentally double-posted xd
     
    nineko likes this.