As many of you may already know, Sonic 2 has a couple of very interesting and rather useful unused objects leftover from Sonic 1, like the breakable walls and purple rocks. As it turns out, the collapsing platforms in Hidden Palace (Object 1A) are derived from Sonic 1s' collapsing slopes in Green Hill, and will act just like them in other zones (except for Oil Ocean, it's supported their but unused)! This is very convenient if your porting Green Hill Zone! If your anything like me, you might want to give them alternative graphics and place them in your own custom zones as well. Sadly, however, they suffer from a nasty issue when used as is: Try to ignore the loud background music X3 They will clip you through floors! In the best of cases, this can be avoided by jumping at the right time, or it will push you into a lower path. But if used near the death barrier (something that actually happens in GHZ3), it can teleport you directly into it and instakill you for no good reason Now, I spent way too long tracking this down, so I have a short answer and a long one. Short answer; find "Obj1A_GHZ_SlopeData:". It should look like this: Code: ; S1 remnant: Height data for GHZ collapsing platform (unused): ;byte_10C3C: Obj1A_GHZ_SlopeData: dc.b $20,$20,$20,$20,$20,$20,$20,$20,$21,$21,$22,$22,$23,$23,$24,$24 dc.b $25,$25,$26,$26,$27,$27,$28,$28,$29,$29,$2A,$2A,$2B,$2B,$2C,$2C; 16 dc.b $2D,$2D,$2E,$2E,$2F,$2F,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30; 32 Copy paste this line underneath it: Code: dc.b $30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30,$30; 48 ;dummy values, to prevent accidentally going out of bounds. And that's that. And now for the long answer, based on how I tracked the issue down! Because I want to justify being scared of this issue for so damn long :Y The first thing that I thought might cause the problem was the way the platform breaks, but even if you disable that (making it just a standard sloped platform), the issue still occurs. So I set about trying to learn how it collided with things, because object collision is a thing I've been rather fuzzy on. The meat of how the platform collides is in the SlopedPlatform routine, which is only used by this object and the seesaws. Notably, neither of these clip into the ground the way the Green Hill platforms do; I was initially worried that might be contributing to the issue. I also immediately found out that it had an input that wasn't being set; it apparently accepts the objects height in d3, at least according to the comments in the disassembly. Not only was d3 not being set by object 1A, but it wasn't even referenced anywhere in the objects code, so it was likely just dumping nonsense from whatever previous use d3 had into the routine, which could definitely lead to wacky behavior. Fixing that by setting it to a reasonable value did nothing to the issue though. I tried several different values and nothing noticeably changed... With my options pretty much exhausted regarding potential issues with calling the routine (everything seemed to be passed in properly, and there was no real collision code outside of that call), I got to work commenting the entire routine. Here it is, if your curious. I was able to follow along relatively well, even if I did get tripped up by some bitwise operations being used on numerical values... Code: ; ||||||||||||||| S U B R O U T I N E ||||||||||||||||||||||||||||||||||||||| ; ; input variables: ; d1 = object width ; d3 = object height ; d4 = object x-axis position ; ; address registers: ; a0 = the object to check collision with ; a1 = sonic or tails (set inside these subroutines) ; a2 = height data for slope ; loc_19C8A: SlopeObject: SlopedPlatform: lea (MainCharacter).w,a1 ; a1=character moveq #p1_standing_bit,d6 ;saving standing bit in d6 (faster/smaller most likely) movem.l d1-d4,-(sp) ;store details in stack to check with tails bsr.s SlopedPlatform_SingleCharacter ;run actual SlopedPlatform code movem.l (sp)+,d1-d4 ;restore details in stack to check for tails lea (Sidekick).w,a1 ; a1=character addq.b #1,d6 ;this presumably adjusts standing bit to deal with tails ; loc_19CA0: SlopedPlatform_SingleCharacter: btst d6,status(a0) ;is this player already standing on us? beq.w SlopedPlatform_cont ;if not, this checks if player is on us and sets thier on object flag move.w d1,d2 ;copy given object width to d2 add.w d2,d2 ;object width * 2 btst #1,status(a1) ;is this player in the air? bne.s loc_19CC4 ;if so, branch move.w x_pos(a1),d0 ;save players x_pos in d0 sub.w x_pos(a0),d0 ;subtract our own x_pos from d0 (distance between object and player in x axis?) add.w d1,d0 ;add object width to distance between player and object bmi.s loc_19CC4 ;presumably, if player is no longer on the object width wise, make player fall off cmp.w d2,d0 ;compare distance to width * 2 (presumably checking other side of object) blo.s loc_19CD8 ;if player is indeed on the slope, run normal sloping code. ;this runs when player enters the air while on the platform. ;Clears the on platform flags for both us and the given player loc_19CC4: bclr #3,status(a1) bset #1,status(a1) bclr d6,status(a0) moveq #0,d4 rts ; --------------------------------------------------------------------------- loc_19CD8: ;ISSUE IS MOST LIKELY DOWN HERE!!! move.w d4,d2 bsr.w MvSonicOnSlope ;This subroutine is the likely culprit moveq #0,d4 rts ; =========================================================================== ... ; =========================================================================== ;loc_19BCC: MvSonicOnSlope: btst #3,status(a1) ;is player standing on object? beq.s return_19C0C ;if not, rts move.w x_pos(a1),d0 ;move players x_pos into d0 sub.w x_pos(a0),d0 ;subtract our x_pos (distance between us and object) add.w d1,d0 ;add object width to distance (d1 stores object width from earlier) lsr.w #1,d0 ;bitshift distance from far end of object to the right? (logical shift right, saves sign and makes it 'smaller') btst #0,render_flags(a0) ;is this object mirrored on x axis? beq.s loc_19BEC ;if not, branch not.w d0 ;reverse distance value bitwise? add.w d1,d0 ;add object width to it again (maybe to test other far side?) loc_19BEC: move.b (a2,d0.w),d1 ;this gets a value from the given slope height map into d1 based on d0 (d0 is relative to player position on the object) ext.w d1 ;extend byte value in d1 to a word value move.w y_pos(a0),d0 ;copy our y_pos into d0 sub.w d1,d0 ;subtract value from heightmap from our y_pos moveq #0,d1 ;clear d1 move.b y_radius(a1),d1 ;copy players y_radius into d1 sub.w d1,d0 ;subtract players y_rad from heightmap value relative to our position (ie where they "should" be) move.w d0,y_pos(a1) ;set players y_pos to appropriate position sub.w x_pos(a0),d2 ;subtract player x_pos from our old position sub.w d2,x_pos(a1) ;subtract distance from our actual x_pos (?) return_19C0C: rts I didn't find anything odd that would interact with the regular block based level ground in anyway. I know a lot about how the standing on object flag works, so I knew that it wasn't really able to clip the player into anything as quickly as this issue does, especially without lingering. I thought that it setting the in air flag while I was walking onto solid ground might be an issue, but that didn't have an effect either. So I copied the object into a clear area with no level based ground nearby so I could test it in isolation. And lo and behold, the issue happened even without nearby ground. But it got even weirder then that! With no nearby collision and it's collapsing feature disabled, I found I could walk on it even after it teleported me down! And from there I could walk back to teleport up, or walk a teensy bit more to the side to have a weirdly bumpy ride off of thin air! And that's when it hit me; the MvSonicOnSlope routine accepts collision data, but has no boundary checks! It just uses the players position relative to the object and the objects own width to determine which data to read for the slope! So I went to checkout the data itself. It looked perfectly fine at a glance, and it was also the same size as the data for the hidden palace zone variant of the platform (which obviously works just fine, no weirdness there). So I checked the object width of each variant. Hidden Palace uses a width of $30, but Green Hill uses a width of $34, despite having the same sized data set. This extra width made MvSonicOnSlope read the mappings data after it as being the last 4 bytes of slope, causing it to naturally allow the player to follow that buggy slope section well below the intended area! All that effort, just to find out Sonic Team got lazy! Guess that's what I get for using unused objects