How to: Port S3K Priority to Sonic 1 from RHS’s guide for Sonic 2 + Caterkiller Fix

Discussion in 'Tutorials Archive' started by DemonFox, Sep 9, 2014.

Thread Status:
Not open for further replies.
  1. DemonFox

    DemonFox Newcomer Member

    Joined:
    Aug 15, 2014
    Messages:
    10
    Porting S3K Priority to Sonic 1 - Guide by an ASM Noob​

    ### This guide was originally made to fix the caterkiller bug, assuming you had followed redhotsonic's S3K priority guide for Sonic 2###​
     ​
    Original Guide by redhotsonic (RHS):

    http://sonicresearch.org/forums/index.php?showtopic=3183

    http://info.sonicretro.org/SCHG_How-to:port_S3K_Priority_Manager_into_Sonic_2


    All credit goes to RHS for the original guide! - I dont want you guys crediting me for his work OK!!!!


    If you are fine and came accross the Caterkiller bug – the only problem that I’ve found by adding this to my hack - jump to step 8 (the only Step I really was meaning to post)


    However if you need more guidance adapting the guide for Sonic 1 start at Step 1:

    Step 1: Understanding why you are porting this to sonic 1

    If you havent read RHS's guide go back and read it to understand the basics and know why you are porting this to your hack!

    EDIT : For those who want the basic reason:

    • It’s was pretty straight forward to implement into Sonic 1 from following RHS's guide you just needed to not follow the Sonic 2 specific portions, i.e.
      Sonic 1's constants/variables (i.e. Obinertia vs inertia)
      Priority = Obpriority (WTF right!)
    [*]Skip Sonic 2 bosses (Step 8 + 9 of S3K guide), special stage
    [*]For "Step 10 update (15/07/12) - Fix the priority for when the main character is dead"
    • Search Sonic.asm for ExecuteObjects - you should find the correct section (loc_D368)
      ExecuteObjects
    [*]Skip Step 11 - Fix the priority for Special Stages", "Step 12 - Fix the CNZ pull-spring"
    [*]If this is all the help you needed sweet jump to step 8


    However if you need some more help continue to step 2 the quick guide to port S3K priority to S1

    • I am not going to copy and paste RHS's tutorial and change the constants/variables!
      So if you want more explanation as to what each step is doing go back and read RHS's Guide


    Step 2: Getting a free Universal SST

    Notes: Before you start remember: EVERY SST MUST BE EQUATED i.e. $18(a0), should be obpriority(a0).

    • Open up your Constants.asm and you'll see:

    obInertia:            equ  $14               ; potential speed (2 bytes)
    Change to:


    obInertia:            equ  $20               ; potential speed (2 bytes) ; Changed from 14
    Now go to:


    obActWid:           equ $19                ; action width
    Change to:


    obActWid:           equ $14                ; action width ; from 19
    • This allows ObPriority to be used as a word ($18 and $19)!
    (just like Sonic 2, changing these appears to free a universal SST, apart from the Caterkiller bug)


    (Original SST guide by RHS: http://sonicresearch.org/forums/index.php?showtopic=3102)


     Step 3:  Changing DisplaySprite DisplaySprite1, and Create DisplaySprite2

    ### After starting this step dont build your rom until you have at least finished step 6 as shit will not work correctly ###

    Open sub DisplaySprite.asm and replace everything with this:


    ; ---------------------------------------------------------------------------
    ; Subroutine to    display    a sprite/object, when a0 is the    object RAM
    ; ---------------------------------------------------------------------------

    ; ||||||||||||||| S U B    R O U T    I N E |||||||||||||||||||||||||||||||||||||||


    DisplaySprite:
            lea    (v_spritequeue).w,a1
            adda.w  obpriority(a0),a1 ; get sprite priority
            cmpi.w    #$7E,(a1)    ; is this part of the queue full?
            bcc.s    DSpr_Full    ; if yes, branch
            addq.w    #2,(a1)        ; increment sprite count
            adda.w    (a1),a1        ; jump to empty position
            move.w    a0,(a1)        ; insert RAM address for object

        DSpr_Full:
            rts    

    ; End of function DisplaySprite


    ; ---------------------------------------------------------------------------
    ; Subroutine to    display    a 2nd sprite/object, when a1 is    the object RAM
    ; ---------------------------------------------------------------------------

    ; ||||||||||||||| S U B    R O U T    I N E |||||||||||||||||||||||||||||||||||||||


    DisplaySprite1:
            lea    (v_spritequeue).w,a2
            adda.w  obpriority(a1),a2
            cmpi.w    #$7E,(a2)
            bcc.s    DSpr1_Full
            addq.w    #2,(a2)
            adda.w    (a2),a2
            move.w    a1,(a2)

        DSpr1_Full:
            rts    

    ; End of function DisplaySprite1

    ; ---------------------------------------------------------------------------
    ; Subroutine to display a sprite/object, when a0 is the object RAM
    ; and d0 is already (priority/2)&$380
    ; ---------------------------------------------------------------------------

    ; loc_16530:
    DisplaySprite2:
        lea    (v_spritequeue).w,a1
        adda.w    d0,a1
        cmpi.w    #$7E,(a1)
        bhs.s    return_16542
        addq.w    #2,(a1)
        adda.w    (a1),a1
        move.w    a0,(a1)

    return_16542:
        rts


    Step 4:  Setting everything up to use S3K Priorty

    ### Note: you will want to read and understand Steps 4-6 and do them all at the same time due to the number of files your checking ###

    Also you better have a Hell of a lot of free time on your hands, and have a good text editor (i.e. Editpad lite) that can open tonnes of files at once so you dont waste time double checking files.


    Open Sonic.asm + all _incObj files, and start searching for "obpriority"

    • S3K Obpriority is a word so all objects have to be changed to use a word i.e:
    Example 1


    move.b #0,obpriority(a0)
    change to:


    move.w #0,obpriority(a0) ;note the move is now ".w"
    ;just in case you didnt know what the hell a word is
    Example 2


    move.b #1,obpriority(a0)
    changes to this:


    move.w #$80,obpriority(a0)
    RHS's Priority Table for quick conversion


    ; ===============================
    ; TABLE CONVERSION FROM S2 (and S1) TO S3K
    ; ===============================
    ; | | S 2 | S3K |
    ; |---|-----|-----|
    ; | ~ | # | #$ |
    ; | P | 0 | 0 |
    ; | R | 1 | 80 |
    ; | I | 2 | 100 |
    ; | O | 3 | 180 |
    ; | R | 4 | 200 |
    ; | I | 5 | 280 |
    ; | T | 6 | 300 |
    ; | Y | 7 | 380 |
    ; ===============================


    Step 5:  Correcting Copiers, Compares, and making sure Objects Calculate correctly

    • Copiers - Example

    move.b obpriority(a0),obpriority(a1)
    changes to:


    move.w obpriority(a0),obpriority(a1)
    • Compairs - Example
    Code:
    cmpi.b #2,obpriority(a0)
    changes to:


    cmpi.w #$100,obpriority(a0)
    • Making sure Objects Calculate correctly - Example
    Code:
    move.b obpriority(a0),obpriority(a1)
    subi.b #1,obpriority(a1)
    changes to:


    move.w obpriority(a0),obpriority(a1)
    subi.w #$80,obpriority(a1)


    Step 6:  Set objects that use tables to use correct S3K priority

    • move.b (a1)+,obpriority(a0)

    move.b (a1)+,obpriority(a0)
    • insert the following after:
    Code:
    move.w obpriority(a0),d0 
    lsr.w #1,d0 andi.w #$380,d0 
    move.w d0,obpriority(a0)
    So it looks like:


    move.b (a1)+,obpriority(a0)
    move.w obpriority(a0),d0
    lsr.w #1,d0 andi.w #$380,d0
    move.w d0,obpriority(a0)[/asm]


    Step 7:  Fixing priority when Sonic is dead

    Open Sonic.asm and go to "ExecuteObjects:"


    Replace ExecuteObjects code with the following:


    ExecuteObjects: ; XREF: GM_Title; et al
    lea (v_objspace).w,a0 ; set address for object RAM
    moveq #$7F,d7
    moveq #0,d0
    cmpi.b #6,(v_player+obRoutine).w
    bcc.s loc_D362

    loc_D348:
    move.b (a0),d0 ; load object number from RAM
    beq.s loc_D358
    add.w d0,d0
    add.w d0,d0
    movea.l Obj_Index-4(pc,d0.w),a1
    jsr (a1) ; run the object's code
    moveq #0,d0

    loc_D358:
    lea $40(a0),a0 ; next object
    dbf d7,loc_D348
    rts
    ; ===========================================================================

    loc_D362:
    cmpi.b #$A,(v_player+obRoutine).w ; Has Sonic drowned?
    beq.s loc_D348 ; If so, run objects a little longer
    moveq #$1F,d7
    bsr.s loc_D348
    moveq #$5F,d7

    loc_D368:
    moveq #0,d0 ; Clear d0 quickly
    move.b (a0),d0 ; get the object's ID
    beq.s loc_D37C ; if it's obj00, skip it
    tst.b obRender(a0) ; should we render it?
    bpl.s loc_D37C ; if not, skip it
    move.w obpriority(a0),d0 ; move object's priority to d0
    btst #6,obRender(a0) ; is the compound sprites flag set?
    beq.s loc_D378 ; if not, branch
    move.w #$200,d0 ; move $200 to d0

    loc_D378:
    bsr.w DisplaySprite2
    loc_D37C:
    lea $40(a0),a0
    dbf d7,loc_D368
    rts
    ; End of function ExecuteObjects

    Note: Again I am an ASM noob so if this is wrong just let me know, I havent seen any problems with it, but my hack is changed so that sprites dont freeze when sonic dies

    Step 8: Fixing the Caterkiller bug

    Providing you followed RHS's original guide or this guide correctly you should be thinking sweet I’ve ported S3K priority to Sonic 1


    However if you go to Marble Zone!

    [​IMG]

     ​
    Oh F#@$ You Can walk right through the Caterkillers!

    • Open: Object 78 - Caterkiller enemy             (MZ, SBZ)
      (The problem is easily fixed – it seems that moving obInertia to 20 has caused the problem)
    • This is fixed by simply replacing all instances obInertia to $1C / obAnim from @move down until the end of object 78.
    i.e


    ....
    @move:
            addq.b    #2,ob2ndRout(a0)
            move.b    #$10,$2A(a0)
            move.w    #-$C0,obVelX(a0)
            move.w    #$40,$1C(a0) ;$1C changed from obInertia
            bchg    #4,$2B(a0)
            bne.s    loc_16AFC
            clr.w    obVelX(a0)
            neg.w    $1C(a0)
    ....

    Step 9: Credit!

    And if you needed help adapting his guide for Sonic 1 (and had to use my guide) please credit both of us, Thanks
     
    Last edited by a moderator: Sep 21, 2014
    Nat The Porcupine likes this.
  2. redhotsonic

    redhotsonic Also known as RHS Member

    Joined:
    Aug 10, 2007
    Messages:
    2,969
    Location:
    England
    Not bad, but rather than saying, "You should follow his guide but avoid doing special stages and the bosses, etc.", you should say, "You need to follow steps 1, 2, 3, whatever steps or part of this step of the priority manager guide and steps 1 and/or 2 of the SST guide".  Your step 2 says follow my step 2, but from which guide?

    In other words, pretend you have to teach a baby.  A baby needs to understand your guide.  Then you can say you've guided people putting the priority manager into Sonic 1, because even the stupid could then do this.
     
    Last edited by a moderator: Sep 9, 2014
  3. Irixion

    Irixion Well-Known Member Member

    Joined:
    Aug 11, 2007
    Messages:
    670
    Location:
    Ontario, Canada
    You callin me a baby motherfucka?

    Seriously though, I'm pretty impressed with this guide as it is, however it does need some work. As RHS mentioned, this needs some clarification on a few points. I'd really like to see where this can go :)
     
  4. DemonFox

    DemonFox Newcomer Member

    Joined:
    Aug 15, 2014
    Messages:
    10
    Updated the guide based on comments to make it more friendly for Sonic 1 users, please let me know if there are any issues with the guide

    Replies to questions can be found here:

    Edit: @Irixion, there would be no point showing screenshots (as its overall lag that's improved due to less calculations being needed for each frame for each sprite), and each step apart from 7 & 8 are all changing one thing (the games use of priority, changing it to match S3K)

    For a good example of how it deceases lag check out "Step 15 - Finish" of RHS's guide (including youtube videos and S2 ROM)

    Edit 2: @Irixion: I understand what you mean, but Sonic 2 must have been built directly off of Sonic 1, porting priority simply helps speed up the game when processing large number of sprites on screen (therefore decreasing the slowdown/lag), especially if you also adapt the objectfall/move from S3K for Sonic 1, they just renamed it for Sonic 2 (“ObjectMove”/ “ObjectFall” in S1 and "ObjectMoveandFall"/”sub SpeedToPos” in S1)

    Edit 3: @Neon Newbie: The ASM tagging does not work correctly and then those who need to copy paste wouldnt be able to do so lol, I know it looks better and highlights the correct areas but.......to be honest I cant be arsed fixing up the formating just for that
     
    Last edited by a moderator: Sep 17, 2014
  5. Irixion

    Irixion Well-Known Member Member

    Joined:
    Aug 11, 2007
    Messages:
    670
    Location:
    Ontario, Canada
    You could explain why you're doing step x and how it changes game behaviour, maybe provide screenshots in said comparisons? So far it's fantastic :). Nice to see new comprehensive guides popping up!
     
  6. redhotsonic

    redhotsonic Also known as RHS Member

    Joined:
    Aug 10, 2007
    Messages:
    2,969
    Location:
    England
    Yes, now shut up; it's time for your feeding =P
     
  7. Irixion

    Irixion Well-Known Member Member

    Joined:
    Aug 11, 2007
    Messages:
    670
    Location:
    Ontario, Canada
    Just saw his edited post.

    While RHS's videos show how the game behaves differently in Sonic 1, it'd be interesting to see what the application means in an S1 setting, considering the games are kinda different when it comes to certain things.

    I love the guide though. Someone needs to approve this guy!
     
    Last edited by a moderator: Sep 14, 2014
  8. N30member

    N30member non-pro user btw Member

    Joined:
    Feb 15, 2014
    Messages:
    216
    Location:
    Kazakhstan
    Just change all code into ASM tag, and you'll do fine.
     
  9. redhotsonic

    redhotsonic Also known as RHS Member

    Joined:
    Aug 10, 2007
    Messages:
    2,969
    Location:
    England
    First of all, what's wrong with how he has it set up already? Still perfectly clear.

    Second, if I remember right...

    CODE

    loc_6E5E:
    moveq #0,d1
    cmpi.b #1,d2
    blt.s loc_6E88
    moveq #2,d1ASM

    Code:
    loc_6E5E:moveq #0,d1
    
    cmpi.b #1,d2
    
    blt.s loc_6E88
    
    moveq #2,d1
    
    
    ASM tagging doesn't work as well (needing fixing for a long time now).
     
  10. Clownacy

    Clownacy Retired Staff lolololo Member

    Joined:
    Aug 15, 2014
    Messages:
    1,020
    Retro's still converts tabs (indents?) into spaces, meaning you've gotta redo them all unless you want messy code. That or you start using code tags, and make everything look scruffy. I dunno, code tabs seem to work better here.
     
  11. ThomasThePencil

    ThomasThePencil resident psycho Member

    Joined:
    Jan 29, 2013
    Messages:
    910
    Location:
    the united states. where else?
    I'm still waiting for that magical day where the ASM tag is fixed. :U

    That aside, this is a nice guide, and it's quite well put together if you ask me.
     
Thread Status:
Not open for further replies.