Showing posts with label Sandopolis Zone. Show all posts
Showing posts with label Sandopolis Zone. Show all posts

Thursday, October 19, 2017

The ghosts are already loose

When playing as Knuckles in Sandopolis Zone 2, the ghosts don't wait for Last_star_post_hit to have a non-zero value before spawning. And later, when you reach the capsule, you find that it's already been opened.


Continuing my point from last time, this is because Knuckles' story takes place after Sonic's, and no one re-trapped the ghosts in the capsule after Sonic and Tails freed them.

This isn't the only instance of level events in Sonic's story having a tangible effect on Knuckles' playthrough of the level.


When playing as Sonic or Tails, there's a cutscene at the end of Launch Base Zone 1 in which Knuckles throws a bomb into a building, causing it to collapse. Later, when Knuckles plays through the stage, the building has sunk into the floor, revealing the alternate path hidden behind a wall in Sonic and Tails' version of the stage.


In fact, the very same function is called during both Sonic and Knuckles' stories in order to remove the building from the level layout. That should cement any doubts on the issue, concretely proving that my claims are rock solid.

*bricked*

Tuesday, September 12, 2017

That sinking feeling

It's worth pointing out that the only thing preventing the quirk we saw last time from occurring with completely solid level blocks is wall collision: as you may recall, whether a block is solid from the top or from other directions is determined by two separate flags, and the associated behavior is also defined separately. As such, just like top-only blocks, if you're in the air and have any upward momentum, you will not register any collision with the top of fully solid blocks.

Ordinarily, this isn't an issue, because the player will always be falling when they touch the ground. The problem occurs when a level event sets the solid background flag and begins scrolling the background plane upward. In this scenario, it is possible for the floor to rise faster than the player, and since the player is moving upward, no collision is registered.


This can happen during the rising sand sequences in Sandopolis Zone, as well as directly after the Carnival Night Zone act 1 boss, since during this sequence, the foreground plane contains the boss' breakable blocks, where as the entirety of the shaft, including the floor below, is part of the rising background plane.

It doesn't happen in Marble Garden Zone because the player gets pushed up along with the background plane, even in mid-air, and it also doesn't happen at the very end of Flying Battery Zone because there's an invisible solid object rising along with the long floor beam.

Wednesday, September 6, 2017

Act transitions, part 8: Sandopolis Zone

Wrapping things up: besides Angel Island Zone and Icecap Zone, Sandopolis Zone is the only other stage in which the act transition doesn't happen during the act 1 results. Instead, it takes place immediately afterwards, during the fade to black when entering the pyramid. This isn't nearly as exciting as the other two stages, but there you go.


Interestingly, this the only instance in which the player palette gets reloaded in the middle of a stage, which means that if you're playing as Blue Knuckles and turned red upon reverting from a Super transformation (admittedly an infrequent scenario!) then you'll be blue again at the start of act 2.

Tuesday, August 15, 2017

Contextual graphics, part 1

The capsule near the start of Sandopolis Zone 2 uses graphics which do not reappear until the after the boss fight, and so it would be a waste of VRAM if they were loaded the entire time. So instead, the graphics are loaded on the spot via PLC call, much like we saw before in Marble Garden Zone 2.

Unlike the MGZ2 boss however, which is initially hidden from view, the capsule is immediately visible upon spawn. This makes it unsuitable for the capsule to load its own graphics as it spawns: you would catch the art being decompressed on the fly. The solution the developers found was to place a helper object on the loop above the capsule.


Once the player is within range of the object, it loads the capsule's PLC over the graphics for the Skorp and Sandworm enemies. The object's range is quite generous, though, and it is entirely possible to cause the capsule graphics to load without actually taking the loop. This would normally be fine, since there aren't any enemies in the immediate area.


However! If you push the first door in the level all the way open, and then quickly make your way over to the loop, there should be just enough time for you to step into the helper object's range and make it back to the door before it closes.


By the way, the Sandworm enemy's regular appearance is more than just inspired by the Caterkiller enemy in Sonic 1.

Monday, August 14, 2017

A ghost's pumpkin soup

Welcome back. When playing Sandopolis Zone 2 as Sonic or Tails, there actually aren't any ghosts at the very start of the stage. A little bit later, you're forced to break open an animal capsule, releasing the ghouls from within.


Many years ago, the legendary GoldS demonstrated that if you manage to avoid breaking the capsule, then the ghosts appear as soon as you touch a star post. It makes sense: there are no star posts prior to the capsule, so this is a good way to ensure the ghosts are present throughout the rest of the stage, even after you die or enter a bonus stage.


However, it's actually simpler than that. All the ghosts do is wait for Last_star_post_hit to have a non-zero value. When the capsule breaks, it triggers a fake star post with the same X/Y position as the regular act 2 start coords. As a result, if you lose a life after breaking the capsule but before touching the first star post, you'll respawn back at the start of the stage, except with the ghosts already out and a non-zero timer.

Tuesday, August 1, 2017

The same, but different

Alright, one final detail about breakable walls. Did you ever notice that the Knuckles walls from Carnival Night Zone end up reappearing much later in the game, in Sandopolis Zone?


What's interesting about this bit of graphics reuse is that a) it's only between these two, seemingly arbitrary levels, and b) the graphics actually aren't reused at all! Although the sprite mappings are shared between the two levels, the art is not, and the two sprites actually look a bit different from one another.


The reason for the art discrepancy becomes evident when you realize these sprites are not using the player palette or the enemy palette like other common objects: they're using the main level colors in line 2! No wonder they look slightly different, considering the two levels have such distinct color schemes.

Tuesday, July 4, 2017

Boss flash bloopers

The boss of Sandopolis Zone 2 uses two different palettes: one for the metallic interior, loaded over the enemy palette, and another for the stone shell, loaded over the palette for the stage's background, which is obscured at this point. It's actually this second palette that flashes when the boss takes damage.


Something seems a bit off, though: the two darkest colors of the shell don't flash, resulting in this strange outline effect. A quick look at the code reveals the cause:
loc_7820A:
    moveq   #0,d0
    btst    #0,$20(a0)
    bne.s   loc_78218
    addi.w  #$A,d0

loc_78218:
    bsr.w   sub_7825E
    subq.b  #1,$20(a0)
    ...
; ---------------------------------------------------------------------------

sub_7825E:
    lea     word_7826C(pc),a1
    lea     word_78276(pc,d0.w),a2
    jmp     (CopyWordData_3).l
; ---------------------------------------------------------------------------
word_7826C:
    dc.w  $FC6C, $FC6E, $FC70, $FC72, $FC74
word_78276:
    dc.w    $6E,  $24C,   $28,     4,     2
    dc.w   $AAA,  $CCC,  $CCC,  $EEE,  $EEE
There are five addresses, and two sets of five colors, but the copy function being called is CopyWordData_3. As such, only the first three colors will get pushed to CRAM. Replacing it with a call to CopyWordData_5 resolves the issue.


Lava Reef Zone 1 and Sky Sanctuary Zone also have something strange about their boss flashes. Some of the flash colors are actually much darker than the regular colors; that can't possibly be right.


Below is the the code used by the Lava Reef boss. Can you spot the defect?
loc_78C3A:
    moveq   #0,d0
    btst    #0,$20(a0)
    bne.s   loc_78C48
    addi.w  #4,d0

loc_78C48:
    bsr.w   sub_78C98
    subq.b  #1,$20(a0)
    ...
; ---------------------------------------------------------------------------

sub_78C98:
    lea     word_78CA6(pc),a1
    lea     word_78CB2(pc,d0.w),a2
    jmp     (CopyWordData_6).l
; ---------------------------------------------------------------------------
word_78CA6:
    dc.w  $FC26, $FC28, $FC30, $FC38, $FC3A, $FC3C
word_78CB2:
    dc.w    $2A,     6,     2,  $644,  $422,     0
    dc.w   $888,  $AAA,  $CCC,  $AAA,  $CCC,  $EEE
There are six addresses, two sets of six colors, and the copy function being called is CopyWordData_6. At first glance, everything seems to check out.

Look closer. When $20(a0) is even, d0 is incremented to skip the first set of colors and read from the second. But here, it's being incremented by 4, skipping only the first two colors. CopyWordData_6 will then dutifully copy over the next six colors, which are the last four entries from the regular set, and the first two entries from the flashing set.

A similar defect occurs in the Sky Sanctuary boss. Setting d0 to the correct value resolves the issue:


These defects clearly originate from human error. Each boss has its own flash code, so later bosses probably had their code copied and adapted from existing ones, but the programmer forgot to change the function call or the value of d0.

What's interesting to me is how both oversights are self-correcting: once the boss stops flashing, the normal colors are always restored, so it's hard to notice the problem. You have to be paying close attention to the boss while it's flashing, and you need to know the colors are wrong in advance.

Tuesday, May 9, 2017

The solid background flag

During normal operation, Plane A shows the foreground layer the player can interact with, whereas Plane B shows a parallax background which has no influence on gameplay. However, the two planes are completely interchangeable, except for the order the VDP in which draws them.


When you step inside this indoor section, the background in Plane B can no longer be seen, so the game can get rid of it. Instead of scrolling at a slower speed, Plane B is made to scroll at the exact same rate as Plane A. The background patterns are temporarily shifted aside and replaced with a pile of sand, carefully positioned so the highest point lines up with the cork object. Finally, the game turns on the titular background collision flag, which instructs Sonic to also check for collision with Plane B in addition to Plane A.


Everything is ready, so when you destroy the cork object, all the game has to do is start scrolling Plane B up. All the sand patterns have their high priority flags set, so they appear in front of Plane A's tunnel background. However, the terrain patterns in Plane A are also set to high priority, so it covers the rising sand. The result is that the sand appears to emerge from the ground, ostensibly piling up from the nearby torrent.

This trick was first used in Sonic 2 for Hill Top Zone's earthquake sections. In order for the transition to be seamless, the background must first be completely hidden from view, but Marble Garden Zone goes the extra mile.


The stage's regular background is attached to the top of the rising floor, and although vertical scrolling is sacrificed, the horizontal parallax keeps running like normal. While the whole thing is moving upwards. I don't even understand how they got that to work!