Showing posts with label Trivia. Show all posts
Showing posts with label Trivia. Show all posts

Tuesday, October 1, 2019

One Steve Shield Limit

Reader Emi asked:
There's something that always bothered me in sonic 3 with super sonic
Why SS can't use the insta shield? Or why you can't use the insta shield with normal invicibility.
I'm not sure if that's a bug but it feels odd since the rest still can use their special moves as super but sonic can't
The reason for this is twofold.

First off, the insta-shield is implemented as regular power-up -- it is actually a separate object which spawns into the player 1 shield shot when playing as Sonic, and Sonic is also awarded one whenever he loses any other shield. This is because unlike other characters' special moves, the insta-shield must animate independently from Sonic, and it loads its art to the same VRAM slot reserved for shields and invincibility stars.

This is probably why Sonic can't use any shield moves while invincible. Since shields and invincibility share a single VRAM slot, they can't be displayed at the same time (thank goodness), and it would be pretty bad design to let players use shield moves without knowing ahead of time which move Sonic would actually perform. As such, all shield moves are disabled while Sonic's shield is hidden, and this includes Super Sonic.

Of course, you could reasonably argue that since Sonic's shield is hidden, the insta-shield should just override all other shield moves for the duration of the Super form. After all, it's what Hyper Sonic's jump dash does. That would probably work, if not for another VRAM conflict: similar to the insta-shield, the large sparks that trail behind Super characters at high speeds load their art to the same VRAM slot as shields and invincibility stars.


Actually, this is probably why they fixed that Sonic 2 bug where invincibility and Super would stack! It wasn't a problem in Sonic 2 because shields and invincibility used separate VRAM slots, since players could potentially have both at the same time in a 2P game. Anyway, it was probably too much trouble to mediate VRAM usage between the insta-shield and the sparks, so Super Sonic specifically has no jump moves. That much is intentional:
    bclr    #Status_RollJump,status(a0)             bclr    #Status_RollJump,status(a0)
    tst.b   (Super_Sonic_Knux_flag).w               tst.b   (Super_Sonic_Knux_flag).w
    beq.s   Sonic_FireShield                        beq.s   Sonic_FireShield
                                                    bmi.w   Sonic_HyperDash
    move.b  #1,double_jump_flag(a0)                 move.b  #1,double_jump_flag(a0)
    rts                                             rts
; --------------------------------------------- ; ---------------------------------------------

Sonic_FireShield:                               Sonic_FireShield:
    btst    #Status_Invincible,$2B(a0)              btst    #Status_Invincible,$2B(a0)
    bne.w   locret_12A20                            bne.w   locret_11A14
    btst    #Status_FireShield,$2B(a0)              btst    #Status_FireShield,$2B(a0)
    beq.s   Sonic_LightningShield                   beq.s   Sonic_LightningShield
Now, what probably wasn't intentional is how Super Sonic can trigger the bubble shield's bounce effect upon touching the ground in S3A!


Note how in the above bit of code, Sonic's double_jump_flag is still set upon a successful double jump, even when the Super_Sonic_Knux_flag is on. If Sonic happens to have a bubble shield, that will cause the Player_TouchFloor routine to trigger a bubble bounce, despite the initial downward plunge bit never actually taking place.

S&K adds a check for Super_Sonic_Knux_flag to this code, as well as a clumsy character ID check since characters other than Sonic sometimes run through this code too I guess:
    tst.b   double_jump_flag(a0)                    tst.b   double_jump_flag(a0)
    beq.s   locret_130BC                            beq.s   locret_12230
                                                    tst.b   character_id(a0)
                                                    bne.s   loc_1222A
                                                    tst.b   (Super_Sonic_Knux_flag).w
                                                    bne.s   loc_1222A
    btst    #Status_BublShield,$2B(a0)              btst    #Status_BublShield,$2B(a0)
    beq.s   loc_130B6                               beq.s   loc_1222A
    bsr.s   BubbleShield_Bounce                     bsr.s   BubbleShield_Bounce

loc_130B6:                                      loc_1222A:
    move.b  #0,double_jump_flag(a0)                 move.b  #0,double_jump_flag(a0)
What baffles me is, why include that code path at all? If you just remove the Super_Sonic_Knux_flag check, then the invincibility check in Sonic_FireShield will also catch Super Sonic and bail without setting the double_jump_flag. Yes, the game will continue checking the A, B and C buttons once every frame until Sonic lands back on the floor, but guess what? The game already does that for invincibility!

Okay, so the insta-shield is just a regular old object in the shield slot. Does that mean that if we award it to characters other than Sonic, they too can benefit from its unique properties? Not really.


You see, all the interesting stuff is done by the Sonic object itself. So long as his double_jump_flag is set to 1, Sonic's attack radius is increased beyond its normal range. The insta-shield simply plays its animation whenever the flag jumps from 0 to 1, and then at the end of the animation, it increases the flag to 2, returning Sonic's attack radius to normal.

Incidentally, this is the source of another S3A bug: the double_jump_flag is only cleared when Sonic touches the floor, so if the insta-shield's animation ends after Sonic has already landed, the flag will remain stuck at 2 until Sonic touches the floor again, and any double jumps prior to that will be considered to have been "already spent", as it were.

S&K fixes this by checking whether the double_jump_flag has already been cleared before attempting to set it to 2.


In my upcoming ROM hack, which I *swear* isn't cancelled, you can have characters other than Tails as your support character. Shields can still be awarded to player 1, though, so what do we do about the insta-shield art conflict?

Well, the spindash dust object is already working overtime as skid dust, water splashes and the drowning timer, so now it also serves as an insta-shield for player 2. Yeah, it disappears when player 2 jumps in/out of water and fails to show up at all when they're drowning, but as reader Emi notes, blocking the insta-shield altogether would just feel... odd.

Thursday, January 25, 2018

Why do the S monitors in S3A turn Tails into a block of mush?

Several weird things happen when Tails breaks open an S monitor in S3A. First off, he takes on this ungodly scrambled appearance, all while not receiving the customary 50 rings.


Then, although he does become invincible, his speed isn't increased, nor are rings ever drained from his count. He also doesn't glow at all, though by defeating some enemies, we can verify that Flickies still become yellow.


So what's going on here? Well, the short version is that Super Tails simply doesn't exist yet. To get into the nitty-gritty of it however, we need to take a look at the Monitor_Give_SuperSonic function in S3A.

As we previously saw, in S&K this function is broken up into three distinct code paths, and which path is taken depends on the player's current character. In S3A though, the same function is completely linear, which creates some interesting differences in its behavior when playing as Tails. S3A to the left, S&K to the right:
Monitor_Give_SuperSonic:                                Monitor_Give_SuperSonic:
    addq.w  #1,(a2)                                         addq.w  #1,(a2)
    addi.w  #50,(Ring_count).w                              addi.w  #50,(Ring_count).w
    move.b  #1,(Super_Hyper_palette_status).w               move.b  #1,(Super_Hyper_palette_status).w
    move.b  #$F,(Palette_timer).w                           move.b  #$F,(Palette_timer).w
    move.b  #1,(Super_Sonic_Knux_flag).w                    move.b  #1,(Super_Sonic_Knux_flag).w
    move.w  #60,(Super_Hyper_frame_count).w                 move.w  #60,(Super_Hyper_frame_count).w
    move.l  #Map_SuperSonic,(Player_1+mappings).w           ...
    move.b  #$81,(Player_1+object_control).w                move.b  #1,(Super_Tails_flag).w
    move.b  #$1F,(Player_1+anim).w                          move.b  #$29,(Player_1+anim).w
    move.l  #Obj_SuperSonic_Stars,(Super_stars).w
    move.w  #$A00,(Sonic_Knux_top_speed).w                  move.w  #$800,(Tails_top_speed).w
    move.w  #$30,(Sonic_Knux_acceleration).w                move.w  #$18,(Tails_acceleration).w
    move.w  #$100,(Sonic_Knux_deceleration).w               move.w  #$C0,(Tails_deceleration).w
                                                            move.l  #Obj_HyperTails_Birds,(Hyper_Sonic_stars).w
                                                            ...
                                                            move.b  #$81,(Player_1+object_control).w
    move.b  #0,(Player_1+invincibility_timer).w             move.b  #0,(Player_1+invincibility_timer).w
    bset    #Status_Invincible,status_secondary(a1)         bset    #Status_Invincible,status_secondary(a1)
    moveq   #$46,d0                                         moveq   #$9F,d0
    jsr     (Play_Sound_2).l                                jsr     (Play_Sound_2).l
    moveq   #$2C,d0                                         moveq   #$2C,d0
    jmp     (Play_Sound).l                                  jmp     (Play_Sound).l

First off, both versions of the function add 50 rings to the Ring_count RAM variable, no change there. In S3A however, Tails actually uses the Ring_count_P2 variable, a holdover from Sonic 2's 2P mode in which each character kept track of their own ring count. This accounts for Tails' unchanging ring count.

Next, S3A replaces player 1's mappings with the mappings for Super Sonic. In S&K, Sonic is the only character whose sprites change for his super form; S3A assumes that only Sonic will ever turn super, therefore the player should always receive the new mappings. This results in Tails' corrupted appearance.

Only S&K sets what would become the Super_Tails_flag, enabling Super Tails' rotating palette. However, both games set the Super_Sonic_Knux_flag, which enables Super Sonic's rotating palette and makes Flickies turn yellow.

S3A only writes Super Sonic's speed values to Sonic's speed variables, leaving Tails' values unaffected. And finally, as we've seen before, rather than play the regular transformation sound, S3A monitors play a whistling sound instead.


The sprite corruption can be avoided with debug mode. When the player enters debug mode, their mappings are saved to RAM address $FFCA, so they can be restored upon exiting the mode. By waiting out the transformation sequence in debug mode, Tails' old mappings are kept safe at $FFCA and will undo the damage done by the S monitor.

Monday, January 15, 2018

No fun allowed

In S3A only, if you defeat the Blastoid enemies that are placed directly over the special stage rings in Hydrocity Zone 1, you can actually fall through a hole in the floor directly into the ring's secret room.


For whatever reason, in Sonic 3 & Knuckles, these holes were hastily patched up with invisible collision objects, and as a result, Knuckles can't glide-land or climb up on this ledge properly.


Then again, in S3A you can defeat Blastoids by just walking into them, likely because they don't use the regular enemy collision type. So uh, pick your poison, I guess.

Thursday, January 11, 2018

Welcome to the secret special stage

A while ago, I mentioned how there's this obscure feature of debug mode wherein if you hold down the A button while a special stage is loading, which stage is actually chosen is determined by the value of the Sound Test option rather than which emeralds have been collected. This wraps around every eight values, so $00 and $08 both yield stage 1, etc.

For this reason, whenever the Sound Test value ends in either a 7 or an F, the player is taken to a secret special stage, stage 8. Curiously, despite the fact that this stage is never seen during normal gameplay, its palette is actually different between Sonic 3 (left) and Sonic & Knuckles (right):


If you manage to clear this excruciatingly long stage, you're rewarded with the nonexistent eighth chaos emerald, which shares its color with the Flying Battery Zone-themed stage 5:


However, when you clear the same stage in Sonic & Knuckles, the emerald you're awarded is yellow instead:


This is interesting because in Sonic 3, the yellow emerald is the one obtained in the Hydrocity Zone-themed stage 2! In Sonic & Knuckles, it was changed so that stage 2's emerald is orange instead:


So what is the reason for this whole switcheroo? Well, it turns out, the super emeralds from Sonic & Knuckles reuse the same set of palettes as the regular emeralds.


What probably happened is the yellow super emerald was made orange in order to match its sprite from Hidden Palace Zone, and this change retroactively affected the color of the regular emerald as well. Then, since it didn't have a unique color of its own, the eighth emerald was given the (now unused) yellow palette.

Wednesday, January 10, 2018

The hidden homage

While on the subject of special stages, have you ever noticed how the palettes for the special stages in S3A are loosely based on those of game's main levels?


Stage 1 forgoes the color of Angel Island Zone's grass, but the blue skies make it clear, this is act 1 we're talking about. Meanwhile, stage 2 seems to reference Hydrocity Zone's underwater colors rather than its above-water palette:


Stage 3 is based off Marble Garden Zone, but because it's missing both the green grass and the grayish-purple marble colors, you wouldn't really know that from just looking at it:


On the other hand, stage 4's red and white motif under a black sky is clearly reminiscent of Carnival Night Zone:


Stage 6's bright blue and aqua colors are based off the act 2 background of Icecap Zone:


Finally, stage 7 celebrates the checkerboards prevalent throughout Launch Base Zone, substituting white for the yellow sandstone color seen in both acts, but characteristic of the brick buildings from act 1:


Similar connections exist between Sonic & Knuckles' special stages and that game's levels, though generally speaking, they're not nearly as obvious.

But wait, I completely skipped over stage 5! Turns out, it's a clear match for the interior sections of Flying Battery Zone:


This further cements the fact that Flying Battery Zone was originally Zone 5, and to my knowledge it's the only instance in which this fact is exposed to the player without their use of cheat codes.

Monday, January 1, 2018

Once more, from the top

Happy new year! I have survived the holiday season, and if you are reading this, then so have you. Congratulations.

In anticipation of Sonic 3's upcoming anniversary, I've decided to once again spend the days leading up to it discussing stuff that can only be encountered while playing standalone Sonic 3, henceforth referred to as Sonic 3 alone or S3A for brevity. I'll start with a comment by reader Josh Wallen, who asks:
I'd love to learn the details of why entering Sonic 2's level select code and hotswapping the cartridge works, AND why it's so much easier than entering Sonic 3's _actual_ cheat. I seem to recall it having something to do with the FMV meaning the Genesis doesn't check the input on every frame, so maybe you have covered that one...
I haven't, but other people have done so in the past, which is probably what you're remembering. The intended window for entering the S3A level select code is during the short animation that occurs between the SEGA logo and the game's title screen, but as you note, the controllers aren't checked every frame, which causes some inputs to be dropped.


So what's going on? First off, in order to conserve ROM space, each frame in the animation is compressed with Kosinki compression, and must be sequentially decompressed to RAM before being displayed on screen.

The game's developers actually optimized this procedure by spliting a region of RAM into two buffers, so that while one frame is being decompressed into the first buffer, a completed frame in the second buffer can be sent to VRAM through DMA. When the first frame finishes decompressing, the two buffers are swapped and the contents of the first buffer are sent to VRAM, and at the same time a new frame starts decompressing into the second buffer.

Now, the game usually polls the controllers for player inputs during the vertical interrupt period between outputting each frame to the TV screen, thereby ensuring that the inputs are checked 60 times a second together with the game's video output. And therein lies the rub: some of the animation frames are so large, take more than a frame to decompress.

As a result, the game misses the vertical interrupt window and doesn't output a new frame to the TV screen, creating a "lag frame". Which isn't that bad, since we're just showing an already choppy animation at this point. What sucks is that the controllers aren't polled for input either, so any new button presses are silently dropped.

It just so happens that after decompressing each animation frame, the game introduces an artificial 4 frame pause, just to pace the animation. During this pause, the interrupt handler executes normally, so the controllers get polled properly.


As for the cartridge swap trick, that works because Sonic 2 and Sonic 3 use the same RAM address to store their "level select unlocked" flag, and RAM isn't cleared when the console is reset. I would advise against this method, though: you might short-circuit two pins before the ground connects, which could damage your stuff. I recommend just punching the S3A code in as quickly as you can, before the animation advances to the more problematic, larger frames.

Friday, December 22, 2017

That's cheating, but I'll let it slide

Reader Silver Sonic 1992 asks:
A bit unrelated, but is there a reason there is a duplicate of the Sonic's falling animation?
First, a little background. All three characters have three distinct animations that make use of their falling sprites. These animations take up IDs $19 through $1B. Here are the definitions for Sonic's animations:
byte_12C0A:     dc.b    9, $D7, $D8, $FF

byte_12C0E:     dc.b  $40, $8D, $FF

byte_12C11:     dc.b    9, $8C, $8D, $FF
The second one, $1A, is the animation which plays when falling back from taking damage, and consists of only a single frame. The third one, $1B, is used at the start of a few levels, and alternates between the damage frame and a second one to show Sonic flailing his arms as he falls into the stage.

Now the third animation, $19, is used while sliding on stuff like the icy slopes in Icecap Zone 1, and the sand streams in Sandopolis Zone. As it turns out, if the regular falling animation is used for these obstacles, Sonic's sprite actually floats a fair bit off the floor:


The developers' solution was to duplicate the mapping frames used by the falling animation, shift them diagonally down towards the slope, make a copy of the falling anim that points to those frames, and have slides use that anim instead:


Not all slides, however. If the water slides in Hydrocity Zone 2 used the proper sliding anim, you wouldn't be able to see much of your character due to the high walls of the waterway:


In this instance, the developers cheated and made the water slide call the falling anim instead, which means that Sonic is technically hovering in mid-air again.


And that's why there's a duplicate of Sonic's falling animation. Unless you were talking about mapping frames $D0 and $D1. I think those are just unused.

Thursday, December 21, 2017

The underside of a hero

Not even the Special Stage sprites are exempt from historical oversights. Aside from a really bad misalignment with the standing frame, each sprite features a highly-detailed head that uses a bunch of different colors, whereas the torso and the legs seem much rougher in comparison, using just two shades of blue, at times resembling basic 3D polygons.


It would appear that once again, some of Sonic's sprites were left half-unfinished. But that isn't the only oversight these sprites share with the monkey bar animation.


In both Sonic 1 and Sonic 2, the soles of Sonic and Tails' shoes were colored the same as the rest of the shoe: red. For Sonic 3, the developers changed it so all three characters have black soles, but this redesign was never reflected in the Special Stage sprites for any of them.


Given their close tie to Sonic 2, it should be no surprise that Sonic's monkey bar sprites also feature red soles. They're not alone, though: red soles are also present in some rotation sprites used in Hydrocity Zone, Mushroom Hill Zone and Lava Reef Zone, as well as the horizontal "corkscrew" animation, which is lifted directly from Sonic 2.

EDIT: This was pointed out by commenter greenknight9000, which I somehow missed the first time around. My bad!

Wednesday, December 20, 2017

The face of a hero, part 3

In mapping frames $80-$85, all three characters have a set of unique sprites that's only used while swinging across the monkey bars in Flying Battery Zone. Despite clearly sharing the same base as the standing rotation sprites however, at least Sonic's sprites appear to be noticeably less detailed, looking almost unfinished at times:


These sprites are included in standalone Sonic 3, which isn't too surprising when you consider how Flying Battery Zone was originally meant to appear earlier in the game. What's surprising is how they're identical to the sprites later found in Sonic & Knuckles. It seems like a rough version of the animation was first cobbled together, but then the stage itself got canned before the sprites were polished up, and eventually they just forgot about the whole thing.

Particularly interesting is the first frame, which doesn't share much of a likeness with the rest of the Sonic 3 sprites, but is more or less a perfect match for the standing sprite from Sonic 2.


This is probably holdover from the days where Sonic was still using adapted versions of his Sonic 2 sprites, suggesting that at one point they weren't just placeholders, but actually part of the game's design.

Tuesday, December 19, 2017

The face of a hero, part 2

So how come frame $56 looks different from the regular standing sprite? Well, one possibility is that the differences are unintentional: at some point the developers went back and touched up the standing sprite, and frame $56 didn't receive those tweaks by simple virtue of being a separate frame.

Another possibility is that the differences are intentional, arguably to serve as a better inbetween frame for the standing rotation anim. There's a hole in that theory though, which is that the same cross-eyed gaze can be found in a couple of other sprites, such as the hanging animation:


Now, you could argue that the second theory still applies: the developers may have simply based the hanging sprite on frame $56 instead of the correct standing frame. The first theory seems more plausible though, if only for the fact that it has happened on multiple other occasions.

However, as an anonymous commenter pointed out:
Anyhow, what I find interesting about that presumably-early standing sprite is that the shine on Sonic's shoe matches his ducking sprites, where it spontaneously moves.

To me, that is the most convincing argument.

Monday, December 18, 2017

The face of a hero, part 1

Sonic's sprites in Sonic 3 have always been a divisive subject. Some people like them, but most people hate them, and they will go out of their way to make fun of his "baseball mits" and "clown shoes" without prior provocation.

With the release of Sonic Mania, these lovely individuals have seemingly been vindicated, as Sonic's sprites in that title are based off the ones in Sonic 1 and 2. This important design decision then led to fan-made comparisons such as this, to which the True Elite immediately respond by pointing out how cross-eyed the Sonic 3 sprites look.


Except that if you bother playing the game, you realize this is what Sonic's standing sprite actually looks like:


So where did the other sprite come from? We've actually seen it before on this very blog. It's one of the rotation sprites used when standing on rotating objects, such as the barrels in Carnival Night Zone.


This sprite just happens to be slightly different from the regular standing sprite, namely with respect to Sonic's left shoe, his mouth, and his gaze, which does indeed look a bit cross-eyed.

Okay, but how did this relatively obscure sprite end up in the comparison?

Well, as I pointed out back then, the standing rotation sprites take up mapping frames $55 through $5B. Meanwhile, as we recently saw, the actual standing pose is all the way over at mapping frame $BA. Someone comes along to make a rudimentary sprite rip, finds frame $56 long before reaching frame $BA, so they push it to the top of their sprite sheet.

Much later, someone naΓ―vely takes the first sprite in this sheet, blows the pixels up to the size of Legos, and uses them to win an argument on the Internet.

So how come the other characters don't suffer from this kind of mix-up?

Well, as for Tails, frame $56 is significantly different from his standing sprite, which is nearly unchanged from the one in Sonic 2. This makes it unlikely that anyone would confuse the two.


As for Knuckles, he actually uses frame $56 in his main standing animation, in no short part due to his sheer number of unique sprites, which struggle to fit within the 252 mapping frame limit.