optimized object 57 from sonic 1

sooooo there was always a thing with sonic 1 objects that really bothered me a lot like doing this
    move.w    a1,d5
        subi.w    #$D000,d5
        lsr.w    #6,d5
        andi.w    #$7F,d5
        move.b    d5,(a2)+
what this does is calculate where objects are located in object ram and limits it to $7F slots (that being the amount of object ram slots available for sonic 1)
this is used to get child objects adresses in object ram and to do whatever with it
by doing this bit later in code
  moveq    #0,d4
        move.b    (a2)+,d4
        lsl.w    #6,d4
        addi.l    #v_objspace&$FFFFFF,d4
        movea.l    d4,a1
what this does is get the byte stored basically a slot ID in object ram stored in the main object and then multyplies that by $40 (object ssts in sonic 1) whis can be a bit of pain to deal with if you had lets say $42 ssts (if you had followed a guide for s3k object manager witch there is way better ways to import it now days)
or to have $4A ssts if you wanted to do stuff s3k's way these codes in s1 would fail because calculating for $40 in those lsr,lsl lines
other people use mulu/muls but that takes a lot of proframnce so here is my code i optimized in s1 (warning does contain sonic 3 stuffs)
           dc.w  St1Child3 ;0
           dc.w  St1Child6 ; 1
           dc.w  St1Child7 ; 2
           dc.w  St2Child1 ; 3
           dc.w  St2Child2 ;4
           dc.w  St2Child3;5
           dc.w  St2Child4;6
           dc.w  St2Child5;7 ; extra just incase
           dc.w  St2Child6;8 ; extra just incase
; ===========================================================================
; ---------------------------------------------------------------------------
; Object 57 - spiked balls (SYZ, LZ)
; ---------------------------------------------------------------------------
Obj57:                    ; XREF: Obj_Index
        moveq    #0,d0
        move.b    obRoutine(a0),d0
        move.w    Obj57_Index(pc,d0.w),d1
        jsr    Obj57_Index(pc,d1.w)

                jmp  Add_SpriteToCollisionResponseList
; ===========================================================================
Obj57_Index:    dc.w Obj57_Main-Obj57_Index
        dc.w Obj57_Move-Obj57_Index
        dc.w Obj57_Display2-Obj57_Index
; ===========================================================================
        ;  sub.b  d1,d0

        ;  bra.s   SetObj57Normally
Obj57_Main:                ; XREF: Obj57_Index
        addq.b    #2,obRoutine(a0)
        move.l    #Map_obj57,obMap(a0)
        addq.b  #1,$28(a0)
        move.b    $28(a0),d1    ; get object type
        andi.b    #7,d1        ; read only second numbers

                move.b   d1,$29(a0)

        move.b    #4,obRender(a0)
        move.w    #$200,obpriority(a0)
        move.b    #8,obActWid(a0)
        move.w    obX(a0),$3A(a0)
        move.w    obY(a0),$38(a0)
        move.b    #$98,obColType(a0)    ; SYZ specific code (chain hurts Sonic)
        clr.b   $1A(a0)
        cmpi.b    #1,($FFFFFE10).w ; check if level is LZ
        bne.s    loc_107E8
        move.b    #0,obColType(a0)    ; LZ specific code (chain doesn't hurt)
        move.w    #$310,2(a0)
        move.l    #Map_obj57a,obMap(a0)
        move.b    #2,$1A(a0)

        move.b    $28(a0),d1    ; get object type
        andi.b    #$F0,d1        ; read only the    1st digit
        ext.w    d1
        asl.w    #3,d1        ; multiply by 8
        move.w    d1,$3E(a0)    ; set object twirl speed
        move.b    $22(a0),d0
        ror.b    #2,d0
        andi.b    #-$40,d0
        move.b    d0,$26(a0)

            lea    Ob57ChildSSt(pc),a2

        move.b    $28(a0),d1    ; get object type
        andi.w    #7,d1        ; read only the    2nd digit

        move.w    d1,d3
        lsl.w    #4,d3
        move.w    d3,$3C(a0)
                move.w  $3C(a0),$32(a0)
        moveq   #0,d1
        move.b  $29(a0),d1


        bsr.w    SingleObjLoad
        bne.s    Ob57FailToMakeChildSprite

            move.w (a2)+,d0
            move.w  a1,(a0,d0.w)

        move.b    #4,obRoutine(a1)
        move.b    0(a0),0(a1)
        move.l    obMap(a0),obMap(a1)
        move.w    2(a0),2(a1)
        move.b    obRender(a0),obRender(a1)
        move.w    obpriority(a0),obpriority(a1)

        move.b    obActWid(a0),obActWid(a1)
        move.b    obColType(a0),obColType(a1)
        subi.w    #$10,d3
        move.w    d3,$3C(a1)
;        cmpi.b    #1,($FFFFFE10).w
;        bne.s    loc_10890
    ;    tst.b    d3 ; is it the last obj ?
    ;    bne.s    loc_10890
;        move.b    #2,$1A(a1) ; turn its frame to 2


        dbf    d1,Obj57_MakeChain ; repeat for    length of chain


               ; move.w (a2)+,d0
              ;  move.w  (a0,d0.w),a1
    ;        move.w  a0,a2
    ;    cmpi.b    #1,($FFFFFE10).w ; check if level is LZ
    ;    bne.s    Obj57_Move
    ;    movea.w  a1,a0

        move.b    #$8B,obColType(a1)    ; if yes, make last spikeball larger
        cmpi.b    #1,($FFFFFE10).w
        bne.s    ChangeChainFrames
        move.b    #1,$1A(a1)    ; use different    frame
                move.w  $32(a0),d3
                subi.w  #$10,d3

        move.w    d3,$3C(a1)
        clr.w   $32(a0)

               move.b    #0,$1A(a1)
               bra.s    NormallinkSetting
Obj57_Move:                ; XREF: Obj57_Index
        bsr.w    Obj57_MoveSub

        bra.w    Obj57_ChkDel
; ===========================================================================

Obj57_MoveSub:                ; XREF: Obj57_Move
        move.w    $3E(a0),d0
        add.w    d0,$26(a0)
        move.b    $26(a0),d0
        jsr    (CalcSine).l
        move.w    $38(a0),d2
        move.w    $3A(a0),d3
        lea    Ob57ChildSSt(pc),a2
                moveq    #0,d6
        move.b    $29(a0),d6

                move.w (a2)+,d4
            move.w  (a0,d4.w),a1

        moveq    #0,d4
        move.w    $3C(a1),d4
        move.l    d4,d5
        muls.w    d0,d4
        asr.l    #8,d4
        muls.w    d1,d5
        asr.l    #8,d5
        add.w    d2,d4
        add.w    d3,d5
        move.w    d4,obY(a1)
        move.w    d5,8(a1)
        dbf    d6,Obj57_MoveLoop
; ===========================================================================

Obj57_ChkDel:                ; XREF: Obj57_Move
        move.w    $3A(a0),d0
        andi.w    #$FF80,d0
        move.w    ($FFFFF700).w,d1
        subi.w    #$80,d1
        andi.w    #$FF80,d1
        sub.w    d1,d0
        cmpi.w    #$280,d0
        bls.w    Obj57_Display
        move.w    obRespawnNo(a0),d0    ; get address in respawn table
        beq.s    Obj57_Delete    ; if it's zero, object was placed in debug mode
        movea.w    d0,a2    ; load address into a2
        bclr    #7,(a2)    ; clear respawn entry, so object can be loaded again
; ===========================================================================

Obj57_Delete:                ; XREF: Obj57_ChkDel
        moveq    #0,d2
        move.b    $29(a0),d2
        lea    Ob57ChildSSt(pc),a2


            move.w (a2)+,d0
            move.w  (a0,d0.w),a1
        bsr.w    DeleteObject2
        dbf    d2,Obj57_DelLoop ; delete all pieces of    chain
                bsr.w    DeleteObject ; delete main object
; ===========================================================================

         bra.w    DisplaySprite
Obj57_Display:                ; XREF: Obj57_Index
        bsr.w    DisplaySprite
        jmp  Add_SpriteToCollisionResponseList
what this does insted is remove those lines and then makes a table for available words in the object and whever the game loops to spawn an object or loops to calculate an object adress to do (movement and stuffs) it goes to here Ob57ChildSSt that contains the words you stored object slot adresses you stored at the start of code and then when you need to use them to do stuff you just loop a2 and a2 gets the correct stored adresses for the object slots this method uses ssts space so every sprite is an sst used to store where the child object is located at in RAM this is faster than the orignal method although sst space shouldnt be a problem if you have $4A ssts because then you can store over $16 sprites in 1 table and thats the max amount of sprites ive seen sonic 1,2,3,k do with child objects and lines that are changed usually got replcaed by
 move.w (a2)+,d0
            move.w  (a0,d0.w),a1
move.w (a2)+,d0
            move.w  a1,(a0,d0.w)
what the first thing does is get ssts and the objects stored inside them in a1 and the second does is store child objects adresses in object ram in the ssts in Ob57ChildSSt thanks for reading :)
Last edited: