How to free up 2 universal SSTs!

Discussion in 'Engineering & Reverse Engineering' started by redhotsonic, May 8, 2012.

  1. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    9
    18
    United Kingdom
    YouTuber
    WARNING: Please back-up your whole disassembly before following this guide. I will NOT be held responsible if anything goes wrong when following this guide.

    PLEASE NOTE: This guide automatically assumes that all your SST's are equated. If you have made your own objects or ported objects and still have stuff like "move.w #$488,$1E(a0)" instead of "move.w #$488,anim_frame_duration(a0)", you must rename all the SST's so that they use your equates, so they can easily be moved. Otherwise, things will start to go wrong. This is your only warning about this.






    How to free up 2 universal SST's!

    There are a few guides out there to free up SST's, but these only seem to be for Sonic and Tails only. This is great if you want to use a SST for a double-jump flag, or a homing-attack flag, whatever. Then you think that you want to do something bold. Like, you want to follow Module's guide on how to port the S3K object manager to S2 or you want to follow my guide on How to port S3K Priority Manager into S2. I've now got the object manager ported into my hack, but the biggest trouble with the guide, is that you need to free up a universal SST. Module tries to explain that you can expand the SST table, but this is very complicated and annoying, and you have to edit all the other objects, which is tiring. To make his guide a lot easier to port, freeing a universal SST would be a lot easier and a big time-saver. But how?

    Freeing up one of Sonic and/or Tails SST is no good. Because as explains, only Sonic and Tails uses this. All other objects do not. For example, if you had a free SST in Sonic and Tails, say, $34, then move the Priority from $18 to $34, your hack will freeze pretty much immediately when you next start it. That's because the SEGA logo cannot read from Priority anymore, neither can the title screen, neither can any badniks, blah blah blah.

    Well, I'm not going to show you how to free up 1, but how to free up 2 of them! Part 1 is not too complicated, Part 2 is very very easy. BUT, if you plan to port the S3K object manager using Module's guide, I highly advice you to do Part 1 1st.


    If you're only interested in "How to port S3K Priority Manager into S2" guide, then you can skip step 1 if you want to.



    This guide may look really big and you're probably thinking "Oh gawd, this looks tough", but it's actually easy if you read the guide carefully. And I've tried to make it as easy as I can for you and explained as much as I can too!



    PLEASE NOTE: I am using Xenowhirl's 2007 disassembly. I'm not sure if you can use this guide if you have the SVN disassembly, but correct me if wrong (give it a go, you never know). You definitely cannot do it if you are using Hivebrain's disassembly. This is also for Sonic 2 only!






    Part 1 - Free up one universal SST

    Okay, first of all, I must admit, this technically is not universal, but it is "conventions followed by most objects". This is almost as good as universal, and is actually perfect for Module's guide on porting the S3K manager in. Do not worry, I promise part 2 will free up a universal SST. So, let's get started.

    Step 1 - Changing the hardest parts of anim_frame_duration


    Code (ASM):
    1. anim_frame_duration =   $1E
    anim_frame_duration is a word, so we need to convert this to a byte. Doing so is quite easy. If you search through your ASM file for "anim_frame_duration", you see half of them is set to word, and the others are a byte. So, the ones set to a byte do not need editing. The ones set to a word, obviously do. So, to start, go to "loc_A542:" and you'll see:

    Code (ASM):
    1. loc_A542:
    2.     move.w  d0,y_pos(a1)
    3.     move.w  x_pos(a0),x_pos(a1)
    4.     move.l  #$1000505,mapping_frame(a1)
    5.     move.w  #$100,anim_frame_duration(a1)
    6.     rts
    This is part of the object code to trigger the rescue plane and birds from ending sequence. As you can see, it moves a word ($100) to anim_frame_duration. This needs to be turned into a byte, so change it to this:

    Code (ASM):
    1. loc_A542:
    2.     move.w  d0,y_pos(a1)
    3.     move.w  x_pos(a0),x_pos(a1)
    4.     move.l  #$1000505,mapping_frame(a1)
    5.     move.b  #$FF,anim_frame_duration(a1)
    6.     rts
    As you can see, it's now "move.b" and not "move.w". Because of this, it cannot be $100 anymore and must be a byte-length. So, I put it to $FF. It's only $1 byte off, and I checked this in my game, and you won't spot any difference, so this will work fine.




    Next, go to "loc_13FE2:" and you'll see this:

    Code (ASM):
    1. loc_13FE2:
    2.     move.w  #$2D0,anim_frame_duration(a0)
    3.     addq.b  #2,routine(a0)
    4.     rts
    This is part of the "Game Over" object. When you get Game Over, and the text appears, $2D0 gets set to anim_frame_duration. Then every frame, it goes down a byte, and when it finally reaches 0, the game restarts and goes to SEGA (or, it will go to SEGA screen when you press A, B or C). We can't have $2D0 because it's a word. So, change it to this:

    Code (ASM):
    1. loc_13FE2:
    2.     move.b  #$C0,anim_frame_duration(a0)
    3.     addq.b  #2,routine(a0)
    4.     rts
    Now, it is set to $C0 (notice again, it's been changed to "move.b"). Now you're thinking "it's going to count down too quick, surely?" Well, that's what we're about to fix next. Go to "loc_13FEE:" and you'll see

    Code (ASM):
    1.     btst    #0,mapping_frame(a0)
    2.     bne.w   BranchTo17_DisplaySprite
    3.     move.b  (Ctrl_1_Press).w,d0
    4.     or.b    (Ctrl_2_Press).w,d0
    5.     andi.b  #$70,d0
    6.     bne.s   loc_14014
    7.     tst.w   anim_frame_duration(a0)
    8.     beq.s   loc_14014
    9.     subq.w  #1,anim_frame_duration(a0)
    10.     bra.w   DisplaySprite
    See that? It's testing the anim_frame_duration. If 0, branch, otherwise, it will subtract one from anim_frame_duration. It will keep doing this until it branches. These both need to changed to .b, but that's not enough. As said, it's counting down too quickly, so change it, to this:

    Code (ASM):
    1. loc_13FEE:
    2.     btst    #0,mapping_frame(a0)
    3.     bne.w   BranchTo17_DisplaySprite
    4.     move.b  (Ctrl_1_Press).w,d0
    5.     or.b    (Ctrl_2_Press).w,d0
    6.     andi.b  #$70,d0
    7.     bne.s   loc_14014
    8.     tst.b   anim_frame_duration(a0)
    9.     beq.s   loc_14014
    10.     move.b  ($FFFFFE05).w,d0    ; Move Game Frame timer to d0
    11.     andi.b  #3,d0           ; andi d0 by 3
    12.     bne.w   DisplaySprite       ; if d0 does NOT equal 0, skip subtracting 1 byte from anim_frame_duration
    13.     subq.b  #1,anim_frame_duration(a0)
    14.     bra.w   DisplaySprite
    Both anim_frame_duration have been changed from .w to .b again, but there's a bit of extra code here. Before subtracting 1 from anim_frame_duration, it will move the Game Frame Timer to d0 (Game Frame Timer goes up a byte every single frame). The next command will "and" d0 by 3 (so, every frame, d0 will go 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, etc). Then the next command, saying it will branch to DisplaySprite if d0 does NOT equal 0. If it DOES equal 0, it will then subtract 1 from anim_frame_duration and then DisplaySprite. Because of this, it will not subtract 1 from anim_frame_duration so quickly, and therefor, it will take a bit longer for it to reach 0. Instead of subtracting 1 from anim_frame_duration every frame, it subtracts 1 from anim_frame_duration every 4 frames. This works perfectly.




    Now, next, is to do with the "End of level" results screen object. There's quite a lot to do with this object. Instead of doing a lot of coding here similar to "Game Over", I changed anim_frame_duration to objoff_34. objoff_34 is not used in the "End of level" results screen and therefor, is free to use for this object. Because objoff_34 will be set as a word, it will be using objoff_35 too, which again, is free for this object. The ending of each level still works perfectly for me after doing this. So, go to "loc_14118:" and you'll see:

    Code (ASM):
    1. loc_14118:
    2.  
    3.     move.b  d0,mapping_frame(a0)
    4.     bsr.w   sub_13E1C
    5.     move.w  x_pixel(a0),d0
    6.     cmp.w   objoff_30(a0),d0
    7.     bne.w   return_14138
    8.     move.b  #$A,routine(a0)
    9.     move.w  #$B4,anim_frame_duration(a0)
    And change it to this:

    Code (ASM):
    1. loc_14118:
    2.  
    3.     move.b  d0,mapping_frame(a0)
    4.     bsr.w   sub_13E1C
    5.     move.w  x_pixel(a0),d0
    6.     cmp.w   objoff_30(a0),d0
    7.     bne.w   return_14138
    8.     move.b  #$A,routine(a0)
    9.     move.w  #$B4,objoff_34(a0)
    Please note: that it's still "move.w" and this is because further down, it will be doing "subq.w" an they cannot be changed to .b, as they do it for multiple places which uses words. That's another reason why I'm using objoff_34. It's just a lot easier and simpler than doing a lot of calculations, and that might slow down the results screen, which we do not want. For this object, it will always be .w and not .b, so just make sure of that. Anyway...


    Next, go to:

    Code (ASM):
    1. loc_1419C:
    2.     subq.w  #1,anim_frame_duration(a0)
    3.     bne.s   BranchTo18_DisplaySprite
    4.     addq.b  #2,routine(a0)
    And change it to:

    Code (ASM):
    1. loc_1419C:
    2.     subq.w  #1,objoff_34(a0)
    3.     bne.s   BranchTo18_DisplaySprite
    4.     addq.b  #2,routine(a0)

    Next, go to:

    Code (ASM):
    1. loc_141E6:
    2.     add.w   d0,($FFFFFF8E).w
    3.     tst.w   d0
    4.     bne.s   loc_14256
    5.     move.w  #$C5,d0
    6.     jsr (PlaySound).l
    7.     addq.b  #2,routine(a0)
    8.     move.w  #$B4,anim_frame_duration(a0)
    9.     cmpi.w  #1000,($FFFFFF8E).w
    10.     bcs.s   return_14254
    11.     move.w  #$12C,anim_frame_duration(a0)
    12.     lea next_object(a0),a1 ; a1=object
    And change to:

    Code (ASM):
    1. loc_141E6:
    2.     add.w   d0,($FFFFFF8E).w
    3.     tst.w   d0
    4.     bne.s   loc_14256
    5.     move.w  #$C5,d0
    6.     jsr (PlaySound).l
    7.     addq.b  #2,routine(a0)
    8.     move.w  #$B4,objoff_34(a0)  ; The time the game waits until the total score has totaled and to move on to next level
    9.     cmpi.w  #1000,($FFFFFF8E).w
    10.     bcs.s   return_14254
    11.     move.w  #$12C,objoff_34(a0) ; The time the game waits until the total score has totaled and do the 'continue' jingle and to move on to next level
    12.     lea next_object(a0),a1  ; a1=object

    Next, go to:

    Code (ASM):
    1. loc_14220:
    2.     _move.b #$3A,0(a1) ; load obj3A (uses screen-space)
    3.     move.b  #$12,routine(a1)
    4.     move.w  #$188,x_pixel(a1)
    5.     move.w  #$118,y_pixel(a1)
    6.     move.l  #Obj3A_MapUnc_14CBC,mappings(a1)
    7.     bsr.w   Adjust2PArtPointer2
    8.     move.b  #0,render_flags(a1)
    9.     move.w  #$3C,anim_frame_duration(a1)
    10.     addq.b  #1,(Continue_count).w
    And change to:

    Code (ASM):
    1. loc_14220:
    2.     _move.b #$3A,0(a1) ; load obj3A (uses screen-space)
    3.     move.b  #$12,routine(a1)
    4.     move.w  #$188,x_pixel(a1)
    5.     move.w  #$118,y_pixel(a1)
    6.     move.l  #Obj3A_MapUnc_14CBC,mappings(a1)
    7.     bsr.w   Adjust2PArtPointer2
    8.     move.b  #0,render_flags(a1)
    9.     move.w  #$3C,objoff_34(a1)
    10.     addq.b  #1,(Continue_count).w

    Next, go to:

    Code (ASM):
    1. loc_142B0:
    2.     tst.w   anim_frame_duration(a0)
    3.     beq.s   loc_142BC
    4.     subq.w  #1,anim_frame_duration(a0)
    5.     rts
    And change to:

    Code (ASM):
    1. loc_142B0:
    2.     tst.w   objoff_34(a0)
    3.     beq.s   loc_142BC
    4.     subq.w  #1,objoff_34(a0)
    5.     rts

    Next, go to:

    Code (ASM):
    1. loc_142CC:
    2.     subq.w  #1,anim_frame_duration(a0)
    3.     bpl.s   loc_142E2
    4.     move.w  #$13,anim_frame_duration(a0)
    5.     addq.b  #1,anim_frame(a0)
    6.     andi.b  #1,anim_frame(a0)
    And change to:

    Code (ASM):
    1. loc_142CC:
    2.     subq.w  #1,objoff_34(a0)
    3.     bpl.s   loc_142E2
    4.     move.w  #$13,objoff_34(a0)
    5.     addq.b  #1,anim_frame(a0)
    6.     andi.b  #1,anim_frame(a0)
    Done. All these changes are just for the "End of level" results screen. Using objoff_34 instead of anim_frame_duration is perfectly fine and causes no troubles whatsoever. Next, everything will be going back to .b and not .w soo...




    Now, there's one more object to deal with. The Tornado (Tails' Plane). Go to "loc_3AB18:" and you'll see:

    Code (ASM):
    1. loc_3AB18:
    2.     clr.w   (Ctrl_1_Logical).w
    3.     lea (MainCharacter).w,a1 ; a1=character
    4.     move.w  x_pos(a0),x_pos(a1)
    5.     clr.w   x_vel(a1)
    6.     clr.w   y_vel(a1)
    7.     clr.w   inertia(a1)
    8.     bclr    #1,status(a1)
    9.     bclr    #2,status(a1)
    10.     move.l  #$1000505,mapping_frame(a1)
    11.     move.w  #$100,anim_frame_duration(a1)
    12.     move.b  #$13,y_radius(a1)
    13.     cmpi.w  #2,(Player_mode).w
    14.     bne.s   loc_3AB60
    15.     move.b  #$F,y_radius(a1)
    Basically, this has the same problem as the first object (triggering the rescue plane and birds from ending sequence). It's moving $100 to anim_frame_duration again, so change it to this:

    Code (ASM):
    1. loc_3AB18:
    2.     clr.w   (Ctrl_1_Logical).w
    3.     lea (MainCharacter).w,a1 ; a1=character
    4.     move.w  x_pos(a0),x_pos(a1)
    5.     clr.w   x_vel(a1)
    6.     clr.w   y_vel(a1)
    7.     clr.w   inertia(a1)
    8.     bclr    #1,status(a1)
    9.     bclr    #2,status(a1)
    10.     move.l  #$1000505,mapping_frame(a1)
    11.     move.b  #$FF,anim_frame_duration(a1)
    12.     move.b  #$13,y_radius(a1)
    13.     cmpi.w  #2,(Player_mode).w
    14.     bne.s   loc_3AB60
    15.     move.b  #$F,y_radius(a1)
    It's now "move.b" instead, and moving $FF instead of $100. $1 byte isn't going to make a difference (I couldn't see a difference).


    Next, go to "loc_3AC56:" (still part of the Tornado object) and you'll see:

    Code (ASM):
    1.     lea (MainCharacter).w,a1 ; a1=character
    2.     move.l  #$1000505,mapping_frame(a1)
    3.     move.w  #$100,anim_frame_duration(a1)
    4.     rts
    And change to:

    Code (ASM):
    1. loc_3AC56:
    2.     lea (MainCharacter).w,a1 ; a1=character
    3.     move.l  #$1000505,mapping_frame(a1)
    4.     move.b  #$FF,anim_frame_duration(a1)
    5.     rts
    Same problem as before really.


    That's the hardest parts done, and be honest, that wasn't hard, was it? =P





    Step 2 - Changing .w to .b in all anim_frame_duration

    This bit is easy, but time consuming. It shouldn't take you any longer than 20 minutes. So, go to the top of your ASM file, or go to "StartOfRom:"

    On your notepad (or whatever you're using), use the search function (Edit > Search). In the search box, search for "anim_frame_duration" (without the "quotation marks" of course).

    For every result you find, if it is has a .w to it, change it to .b. (Please note: If it is already .b then you can leave it alone and does not need changing)


    Example, your first result you come to, should be (at "loc_42E8:):

    Code (ASM):
    1.     move.w  #$2D,anim_frame_duration(a1)
    It's extremely simple, you change it to:

    Code (ASM):
    1.     move.b  #$2D,anim_frame_duration(a1)
    Simple. Do this for all your search results.


    One more incase you're not getting it. The next result (which is actually 2 lines down) is:

    Code (ASM):
    1.     move.w  #$2D,next_object+anim_frame_duration(a1)
    and change to:

    Code (ASM):
    1.     move.b  #$2D,next_object+anim_frame_duration(a1)
    How hard is that, do this with all your results.





    Step 3 - Changing .b to .w back in the ARZ, CNZ and MCZ boss's anim_frame_duration

    Because of step 2, you've probably change .w to .b's anim_frame_duration in ARZ, CNZ and MCZ's bosses. This is a big problem. The bosses HAVE to use these as a word, otherwise the bosses will not work correctly. You cannot change it to another SST, because these have to use universal SST's, as a word, and unfortunately, the bosses are already using all the universal SST's available. So, go to these locations:

    • loc_304D4:
    • loc_30824:
    • loc_30FB8:
    • loc_3130A:
    • loc_31904:
    • loc_31E76:

    At all these locations, where you see a command for anim_frame_duration, change the .b back to .w

    Example, at "loc_304D4:", change:

    Code (ASM):
    1.     move.b  #$488,anim_frame_duration(a0)
    back to this:

    Code (ASM):
    1.     move.w  #$488,anim_frame_duration(a0)
    Do this for all the ones in the list. You MUST change them back to .w at the locations in the above list ONLY.





    Step 4 - Change anim_frame_duration and respawn_index around OPTIONAL, BUT RECOMMENDED

    Okay, you've have free'd an SST that can be used by pretty much any object! Good work, you should be proud. $1E is still anim_frame_duration, but $1F is now free for you to use!

    BUT, if you're planning to follow Module's guide on porting the S3K manager to S2, follow this step. In his guide, he says you need to make the SST respawn_index into a word, instead of a byte. So, we can easily re-arrange this. Search for "anim_frame_duration = $1E" (without the "quotation marks") and change:

    Code (ASM):
    1. anim_frame_duration =   $1E
    to this

    Code (ASM):
    1. anim_frame_duration =   $23

    Then, look for respawn_index and change:

    Code (ASM):
    1. respawn_index =     $23
    to this:

    Code (ASM):
    1. respawn_index =     $1E

    Now, anim_frame_duration is using $23 (it won't use $24 because we changed it to bytes), and respawn_index is now $1E, and because we have made $1F free, respawn_index can be used as a word and can now easily use $1E and $1F! BUT, because of this, ARZ, CNZ and MCZ bosses have become affected again. This is because they're moving a word to anim_frame_duration, which is $23. Because it's moving a owrd, it over-writes $24, which is "routine", causing the game to freeze. Easily fixed. Here's how. You need to go to these labels in the list below and change change anim_frame_duration to respawn_index.

    • loc_304D4:
    • loc_30824:
    • loc_30FB8:
    • loc_3130A:
    • loc_31904:
    • loc_31E76:


    Example, at "loc_304D4:", change:

    Code (ASM):
    1.     move.w  #$488,anim_frame_duration(a0)
    back to this:

    Code (ASM):
    1.     move.w  #$488,respawn_index(a0)
    Do this for all the ones in the list above. The bosses can use respawn_index freely as it is universal and it is a word. Basically, it's doing the same as it used to do with anim_frame_duration (using $1E and $1F like it used to in the first place).



    All done for Part 1. That was easy, hey? Now, for part 2, now this one, is universal, and it a hell of a lot quicker. I free'd up this one for my priority manager, but you can use it for whatever you want.






    Part 2 - Free up the second universal SST

    It's so easy. First, go to Sonic's SST's and you'll see

    Code (ASM):
    1. inertia =       $14 ; and $15 ; directionless representation of speed... not updated in the air
    Change it to

    Code (ASM):
    1. inertia =       $20 ; and $21 ; directionless representation of speed... not updated in the air

    For Sonic and Tails, $20 and $21 is free, so move it there. Why? Simple. $14 is a "convention followed by most objects". I think $15 is still only used by Sonic and Tails, but that doesn't matter. Now, instead of the original $1F, $20 and $21 being free for Sonic and Tails, it's now $15 and $1F that is free for them ($14 is NOT free for Sonic and Tails! About to explain why!)


    SVN user? Read this quote! It's important. If Xenowhirl user, you can ignore the quote.


    Next, go to:

    Code (ASM):
    1. width_pixels =      $19
    and change to

    Code (ASM):
    1. width_pixels =      $14
    width_pixels can be moved to $14. Which means, $19 is now free, and it's universal! How about that? Told you it was piss easy! I am using $19 as part of priority (in S3K's priority manager, the priority is a word, so I use $18 and $19). And that's the reason why $14 isn't free for Sonic and Tails, because it's being used for width_pixel. Yes, you're going to lose a SST from them but it's better to gain a universal SST, right?


    So now, you have $19 free universally. If you did NOT follow step 4 in part 1, then you have $1F free which can be used by almost every object. If you have followed step 4 in part 1, then $1F is still free until you port S3K's object manager in using Module's guide. Also, for Sonic and Tails, you have $15, $1F and $23 free.


    WARNING: If you change the equates to use something else, it can cause problems (mainly ARZ, CNZ and MCZ bosses). For example, if you have these bosses set to respawn_index and then you swap respawn_index with routine, respawn_index will use $24 fine, but as the bosses are using it as a word, it will over-write $25, which is routine_secondary. Then, the game will freeze when you come to one of these bosses. Just a word of warning.






    Bugs

    EDIT: This bug has NOW been fixed. Click here for the fix.

    Following this guide to a clean Sonic 2 disassembly (and my Sonic2Recreation), the ONLY bug I could find was this:

    [​IMG]

    The width_pixels have gone wrong on this, and to be honest, I have no idea why. If anyone could find out why, that would be great. I've looked into it myself, and I don't see why it's gone wrong in the first place, but meh. If I do find a solution, I will report back on how to fix it. I've gone through the whole of S2 with Sonic and Tails, and this was the only thing I spotted that went wrong. Everything else seems to be intact.

    Another width_pixels problem is the ARZ boss, but that as already fucked in the original game. Module has shown in one of his guides how to fix it, although, it wasn't totally fixed. So I added an additional step to his guide (with his permission of course), which can be found here.





    Well, I hope you've enjoyed this guide.

    To celebrate my last guide, I am putting a link to all my guides in my signature, in case you want to know =P

    Any questions and comments are welcome. Any mistakes, let me know. Any problems, let me know.


    Enjoy

    redhotsonic
     
  2. SoullessSentinel

    SoullessSentinel

    Member
    257
    0
    16
    Grimsby, England
    Cxbx-Reloaded
    Freeing a couple of SST entries by cutting down anim_frame_duration to a byte instead of a word, and shuffling things around to free entry $19 globally. I can see how this would be useful for people who have used the other SST entries, without the awkwardness of expanding the size of the SST.
    Not a bad idea at all. I'll keep this in mind for if I ever somehow use up all the free SST entries.
     
  3. MoDule

    MoDule

    Tech Member
    324
    6
    18
    Procrastinating from writing bug-fix guides
    Just to clear things up, the crashing here should actually come from writing a wort to an uneven address, which isn't allowed.

    The object uses multi-sprite mode, which allows a single object to store information for up to 10 sprites. Here's the relevant equates:
    Code (ASM):
    1. ; when childsprites are activated (I.e. bit #6 of render_flags set)
    2. mainspr_mapframe    = $B
    3. mainspr_width       = $E
    4. mainspr_childsprites    = $F    ; amount of child sprites
    5. mainspr_height      = $14
    6. sub2_x_pos      = $10   ;x_vel
    7. sub2_y_pos      = $12   ;y_vel
    8. sub2_mapframe       = $15
    9. sub3_x_pos      = $16   ;y_radius
    10. sub3_y_pos      = $18   ;priority
    11. sub3_mapframe       = $1B   ;anim_frame
    12. sub4_x_pos      = $1C   ;anim
    13. sub4_y_pos      = $1E   ;anim_frame_duration
    14. sub4_mapframe       = $21   ;collision_property
    15. sub5_x_pos      = $22   ;status
    16. sub5_y_pos      = $24   ;routine
    17. sub5_mapframe       = $27
    18. sub6_x_pos      = $28   ;subtype
    19. sub6_y_pos      = $2A
    20. sub6_mapframe       = $2D
    21. sub7_x_pos      = $2E
    22. sub7_y_pos      = $30
    23. sub7_mapframe       = $33
    24. sub8_x_pos      = $34
    25. sub8_y_pos      = $36
    26. sub8_mapframe       = $39
    27. sub9_x_pos      = $3A
    28. sub9_y_pos      = $3C
    29. sub9_mapframe       = $3F
    30. next_subspr     = $6
    If we change width_pixels to $14 it overlaps with mainspr_height. If it's left at $19, it can occupy the unused space between sub4_y_pos and sub4_mapframe. Not sure how any of this should be causing serious problems, though. How exactly is the object going wrong?
     
  4. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    9
    18
    United Kingdom
    YouTuber
    A wort? Of course that isn't allowed XD





    You're an SVN user, so I have none of that above =P


    The object goes wrong when Sonic goes straight through it, then he get's squished by it.

    [​IMG]

    [​IMG]

    [​IMG]


    This seems to be the only object affected. Everything else seems perfectly fine.
     
  5. Hitaxas

    Hitaxas

    Retro 80's themed Twich streamer Member
    This guide interest me, as well as the guide to port the object manager (which I am surprised I never saw, all these years). Nice work mates. Will be using those guides in ssd for sure.
     
  6. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    9
    18
    United Kingdom
    YouTuber
    Reading through all my guides in my signiture, I read through this guide and completely forgot about the bug I mentioned.

    [​IMG]

    Well, I quickly looked into it and have fixed it.


    The problem like Module mentioned, was that part of it's height is involved and over-writes the new width_pixels SST. You cannot change the height's location of this object, otherwise the object will never work. But I realised in this object, that it's priority is used for something different as well. Instead, it's priority is moved to d0 then jumps to DisplaySprite3. So, I made width_pixels do the same thing, and now the object is fine. Anyway, the fix:




    Go to "loc_2ABFA:" and you'll see this:

    Code (ASM):
    1. loc_2ABFA:
    2.     bsr.w   JmpTo49_Adjust2PArtPointer
    3.     move.b  #4,render_flags(a0)
    4.     bset    #6,render_flags(a0)
    5.     move.b  #1,objoff_B(a0)
    6.     tst.b   subtype(a0)
    7.     beq.s   loc_2AC54
    8.     addq.b  #2,routine(a0)
    9.     move.b  #$20,objoff_E(a0)
    10.     move.b  #$18,width_pixels(a0)
    11.     move.w  x_pos(a0),objoff_2E(a0)
    12.     move.w  y_pos(a0),objoff_34(a0)
    13.     move.w  x_pos(a0),d2
    14.     move.w  y_pos(a0),d3
    15.     addi.w  #0,d3
    16.     move.b  #1,objoff_F(a0)
    17.     lea $10(a0),a2
    18.     move.w  d2,(a2)+
    19.     move.w  d3,(a2)+
    20.     move.w  #2,(a2)+
    21.     bra.w   loc_2AE56

    Cut out the line "move.b #$18,width_pixels(a0)" so it's not there anymore. We're going to move it.


    Next, go to "Obj85:" and you'll see this:

    Code (ASM):
    1. Obj85:
    2.     moveq   #0,d0
    3.     move.b  routine(a0),d0
    4.     move.w  off_2ABCE(pc,d0.w),d1
    5.     jsr off_2ABCE(pc,d1.w)
    6.     move.w  #$200,d0
    7.     tst.w   (Two_player_mode).w
    8.     beq.s   loc_2ABA0
    9.     bra.w   JmpTo4_DisplaySprite3


    Just before the "move.w #$200,d0", paste the width_pixel line there. So, you end up with this:

    Code (ASM):
    1. Obj85:
    2.     moveq   #0,d0
    3.     move.b  routine(a0),d0
    4.     move.w  off_2ABCE(pc,d0.w),d1
    5.     jsr off_2ABCE(pc,d1.w)
    6.     move.b  #$18,width_pixels(a0)   ; Now moved here instead of being at loc_2ABFA
    7.     move.w  #$200,d0
    8.     tst.w   (Two_player_mode).w
    9.     beq.s   loc_2ABA0
    10.     bra.w   JmpTo4_DisplaySprite3

    There. That object is now fixed. All other objects, I didn't notice any problems. If you run into anything, let me know!


    Cheers,
    redhotsonic
     
  7. RetroKoH

    RetroKoH

    Member
    1,661
    17
    18
    Project Sonic 8x16
  8. redhotsonic

    redhotsonic

    Also known as RHS Tech Member
    1,587
    9
    18
    United Kingdom
    YouTuber
    Awesome, thanks.


    I've been reading your wiki-adds, and you might want to add some pictures to a lot of them. Except that, keep up the good work.
     
  9. RetroKoH

    RetroKoH

    Member
    1,661
    17
    18
    Project Sonic 8x16
    I've taken note of this. One thing I'm doing is putting together an offline copy of the SCHG for my own use for when I'm not able to get online (Also I might make it a PDF and give it out to anyone who would like one). ALSO it gives me a sandbox to work with. I'm learning how to put more stuff in wiki editing, including pictures and quote boxes. The quality of my wiki pages will improve over time, guaranteed.

    Right now, I might post a couple guides for Sonic 1, based on some fixes from Ready Sonic, and besides that, unless you pump out another Sonic 2 guide, I might take a break, to work on setting up some Sonic 3K pages with Tiddles.
     
  10. Alex Field

    Alex Field

    シュート! カオス・エメラルド・ザが消えようとしている! Member
    158
    88
    28
    Downunda, Mobius
    Sonic the Hedgehog 2+, Sonic the Hedgehog 3+
    @redhotsonic Problem, if you swap "respawn_index" and "anim_frame_duration" in the Github disassembly, Sonic and Tails will flash in the Special Stages.
     
  11. AURORA☆FIELDS

    AURORA☆FIELDS

    The cute one here Tech Member
    216
    24
    18
    Finland
    AMPS
    Nice work bumping a thread that is 8 years old. That said, I've found a lot of bugs with the disassembly, and when I have time I will fix all of them and look into it. Hold tight.