Actions

SCHG How-to

Speed Up Ring Loss Process (With Underwater)

From Sonic Retro

Revision as of 22:55, 6 May 2012 by KingofHarts (talk | contribs) (Part 2: Edited a change in ASM)

Part 2

Ok, so I ported the S3&K priority manager into my hack [Sonic 2 Recreation], and you can make the scattered rings object do something extremely similar. So this is only making one object do it, but because of the amount of rings you can lose, this actually makes a BIG difference (as usual, especially underwater).

Go to "loc_120BA:" (part of the scattered rings object) and delete this line: <asm>

       move.b  #3,priority(a1)

</asm>

When the rings are being created, it won't have to move 3 to it's priority anymore, saving a command per ring created and slightly speeding it up (you'll probably won't notice any difference, but this isn't what I am trying to accomplish here).

Now you're probably thinking "WTF! The rings aren't going to be displayed now!" Well, in a way, you're wrong. It will still be displayed, but with a priority of 0. Now, we do not want that, we still want it to be 3, and we're about to fix it, and this will be what speeds it up dramatically.

Go to "loc_121B8" and you should see a command: <asm>

       bra.w   DisplaySprite

</asm>

We are going to replace this with a new code, similar to how S3K does it. In S2, before it can display the sprite, it converts the object's priority into a word, and then displays it. It does calculations that are about 3 lines long to convert it into a word. When lots of objects use this code every single frame (Sonic and Tails constantly for example), it can be a slow process.

Now, imagine you just got hurt and lost 32 rings, each one of them 32 rings branches to DisplaySprite, does the calculations, then displays the sprite; every single frame! All 32 of them! This slows it down quite a bit! Now, you can't just turn the scattered ring's priority into a word, otherwise it will over-write the scattered rings's "width_pixel". So, what do we do? Well, we can just copy part of the DisplaySprite's coding and insert it into the scattered rings' object coding.

Now, normally, after the rings have jumped to DisplaySprite to convert it's priority into a word, it becomes $180. Look at this:

Priority = 3 (byte) <asm> DisplaySprite:

       lea     (Sprite_Table_Input).w,a1
       move.w  priority(a0),d0                 ; To be deleted
       lsr.w   #1,d0                           ; To be deleted
       andi.w  #$380,d0                        ; To be deleted
       adda.w  d0,a1                           ; To be changed
       cmpi.w  #$7E,(a1)
       bcc.s   return_16510
       addq.w  #2,(a1)
       adda.w  (a1),a1
       move.w  a0,(a1)

return_16510:

       rts

</asm>

Now, Priority = $180 (word)

So, we're going to copy this code, then edit it a bit, then move it to the scattered rings object. So copy it, then move it to where the branch was in the scattered rings object. So you have something looking like this:

WAS: <asm> loc_121B8:

       tst.b   (Ring_spill_anim_counter).w
       beq.s   BranchTo5_DeleteObject
       move.w  (Camera_Max_Y_pos_now).w,d0
       addi.w  #$E0,d0
       cmp.w   y_pos(a0),d0
       bcs.s   BranchTo5_DeleteObject
       bra.w   DisplaySprite

</asm>

And change that to this: <asm> loc_121B8:

       tst.b   (Ring_spill_anim_counter).w
       beq.s   BranchTo5_DeleteObject
       move.w  (Camera_Max_Y_pos_now).w,d0
       addi.w  #$E0,d0
       cmp.w   y_pos(a0),d0
       bcs.s   BranchTo5_DeleteObject
       lea     (Sprite_Table_Input).w,a1       ; To be changed
       move.w  priority(a0),d0                 ; To be deleted
       lsr.w   #1,d0                           ; To be deleted
       andi.w  #$380,d0                        ; To be deleted
       adda.w  d0,a1                           ; To be deleted
       cmpi.w  #$7E,(a1)
       bcc.s   +
       addq.w  #2,(a1)
       adda.w  (a1),a1
       move.w  a0,(a1)

+

       rts

</asm>

"To be changed" means that line is going to be edited and the "To be deleted", well, guess what we will do with that? =P

Change <asm>

       lea     (Sprite_Table_Input).w,a1       ; To be changed

</asm>

To this: <asm>

      lea     Sprite_Table_Input+$180,a1

</asm>

As we now know 3 would equal $180, we can just add straight to a1. No more calculations every single frame, we've already done it! You should have something like this now: <asm> loc_121B8:

       tst.b   (Ring_spill_anim_counter).w
       beq.s   BranchTo5_DeleteObject
       move.w  (Camera_Max_Y_pos_now).w,d0
       addi.w  #$E0,d0
       cmp.w   y_pos(a0),d0
       bcs.s   BranchTo5_DeleteObject
       lea     Sprite_Table_Input+$180,a1
       cmpi.w  #$7E,(a1)
       bcc.s   +
       addq.w  #2,(a1)
       adda.w  (a1),a1
       move.w  a0,(a1)

+

       rts

</asm>

So, what have we done? Well, we saved a line of it branching somewhere for a start, it's already there, so that's a plus! Also, we're moving $180 straight to a1, rather than doing them 3 lines of calculations! What a time saver! ALL done. That was easy, eh? Now your scattered rings will be even quicker, hopefully not slowing anything else down!

Part 2.5 (optional)

This is optional; you do not have to do it if you do not want to.

If you look at the code you just edited: <asm> Obj_37_sub_4:

       addq.b  #2,routine(a0)
       move.b  #0,collision_flags(a0)
       move.b  #1,priority(a0)
       bsr.w   sub_11FC2

Obj_37_sub_6:

       lea     (byte_1237A).l,a1
       bsr.w   AnimateSprite
       bra.w   DisplaySprite
===========================================================================

BranchTo5_DeleteObject

       bra.w   DeleteObject

</asm>

You can see a command move 1 to priority, and displaying it again. This is for when you collect the rings (when the rings turn into them sparkly effects). You can do something extremely similar here if you like. It will make quite a bit of a difference if you collect a lot of scattered rings at the same time, otherwise, it won't do too much. If you want it to do the same, then you can. But it won't be $180 again! When 1 has been through DisplaySprite's calculations, it will equal $80 instead!

So, at "Obj_37_sub_4:", delete this line/command: <asm>

       move.b  #1,priority(a0)

</asm>

Then, at "Obj_37_sub_6:", replace: <asm>

       bra.w   DisplaySprite

</asm>

with this: <asm>

       lea     (Sprite_Table_Input).w,a1
       adda.w  #$80,a1
       cmpi.w  #$7E,(a1)
       bcc.s   +
       addq.w  #2,(a1)
       adda.w  (a1),a1
       move.w  a0,(a1)

+

       rts

</asm>

So you have something like this: <asm> Obj_37_sub_4:

       addq.b  #2,routine(a0)
       move.b  #0,collision_flags(a0)
       bsr.w   sub_11FC2

Obj_37_sub_6:

       lea     (byte_1237A).l,a1
       bsr.w   AnimateSprite
       lea     (Sprite_Table_Input).w,a1
       adda.w  #$80,a1
       cmpi.w  #$7E,(a1)
       bcc.s   +
       addq.w  #2,(a1)
       adda.w  (a1),a1
       move.w  a0,(a1)

+

       rts

</asm>

Done: you've made it slightly faster again!

SCHG How-To Guide: Sonic the Hedgehog 2 (16-bit)
Fixing Bugs
Fix Demo Playback | Fix a Race Condition with Pattern Load Cues | Fix Super Sonic Bugs | Use Correct Height When Roll Jumping | Fix Jump Height Bug When Exiting Water | Fix Screen Boundary Spin Dash Bug | Correct Drowning Bugs | Fix Camera Y Position for Tails | Fix Tails Subanimation Error | Fix Tails' Respawn Speeds | Fix Accidental Deletion of Scattered Rings | Fix Ring Timers | Fix Rexon Crash | Fix Monitor Collision Bug | Fix EHZ Deformation Bug | Correct CPZ Boss Attack Behavior | Fix Bug in ARZ Boss Arrow's Platform Behavior | Fix ARZ Boss Walking on Air Glitch | Fix ARZ Boss Sprite Behavior | Fix Multiple CNZ Boss Bugs | Fix HTZ Background Scrolling Mountains | Fix OOZ Launcher Speed Up Glitch | Fix DEZ Giant Mech Collision Glitch | Fix Boss Deconstruction Behavior | Fix Speed Bugs | Fix 14 Continues Cheat | Fix Debug Mode Crash | Fix 99+ Lives | Fix Sonic 2's Sega Screen
Design Choices
Remove the Air Speed Cap | Disable Floor Collision While Dying | Modify Super Sonic Transformation Methods & Behavior | Enable/Disable Tails in Certain Levels | Collide with Water After Being Hurt | Retain Rings When Returning at a Star Post | Improve the Fade In\Fade Out Progression Routines | Fix Scattered Rings' Underwater Physics | Insert LZ Water Ripple Effect | Restore Lost CPZ Boss Feature | Prevent SCZ Tornado Spin Dash Death | Improve ObjectMove Subroutines | Port S3K Rings Manager | Port S3K Object Manager | Port S3K Priority Manager | Edit Level Order with ASM‎ | Alter Ring Requirements in Special Stages | Make Special Stage Characters Use Normal DPLCs | Speed Up Ring Loss Process | Change spike behaviour in Sonic 2
Adding Features
Create Insta-kill and High Jump Monitors | Create Clone and Special Stage Monitors | Port Knuckles
Sound Features
Expand Music Index to Start at $00 | Port Sonic 1 Sound Driver | Port Sonic 2 Clone Driver | Port Sonic 3 Sound Driver | Port Flamewing's Sonic 3 & Knuckles Sound Driver | Expand the Music Index to Start at $00 (Sonic 2 Clone Driver Version) | Play Different Songs Per Act
Extending the Game
Extend the Level Index Past $10 | Extend the Level Select | Extend Water Tables | Add Extra Characters | Free Up 2 Universal SSTs