Under the Microscope: Sokkou Seitokai

In this edition, Sokkou Seitokai (a.k.a. Sonic Council), a Saturn fighting game based on a manga series that ran in Gamest magazine, goes under the microscope.

It’s well-documented (in Japanese and in English) that this game has several bonus features: three extra characters, two alternate voice options, and a goofy mode that makes the menu sound effects into cat meows.

To get at these bonus features is quite a slog, however — you need to clear the game’s story mode seven times to enable all of them. But I found a shortcut method! Details on how it works are below, along with information on another bonus feature I came across while looking at the game data.


Saving six playthroughs

I only promise that this method for unlocking Sokkou Seitokai’s bonuses will be shorter than the normal one, not that it will be all that short.

Step one is to clear story mode with a character of your choice. Sorry, there’s no way around this part — you actually have to beat the game once.

Aya Sakai’s ending sequence.

At the end of the staff credits, you’ll see the screen below — it’s the final one that acknowledges Banpresto (株式会社バンプレスト) and Shinseisha (株式会社新声社).

The Banpresto / Shinseisha screen.

While it’s visible, enter this sequence:

A, B, X, Z, L, X

If you make a mistake, start over — but be quick, because this screen is only visible for a few seconds.

After entering the code, you’ll eventually wind up back at the title screen. Hold L and press Start to make a voice clip start playing.

The title screen.

The voice clip indicates that we’ve just unlocked Akio Shibata, the boss character. He’s available from the character select screen. But don’t go there yet; there’s more to do.

On the main menu, highlight Options, then hold L+R and press B. Another voice clip will play, and you’ll be returned to the title screen. We’ve just unlocked Uragiri no Ai.

The main menu.

Press Start to return to the main menu, then plug a Controller into port 2 (or if one was already connected, unplug it and plug it back in). Another voice clip will play, and Kage Naoko will be unlocked.

You can access Uragiri no Ai and Kage Naoko from the character select screen by pressing Start while highlighting Ai Honda and Naoko Hattori, respectively.

All three bonus characters available.

Unlocking the three characters makes the alternate System Voice and Chara Voice items available from the options screen.

The fully-populated options screen.

Set System Voice to Type-C and Chara Voice to Type-B to enable the cat sound effects for as long as you can stand them.


Animation test mode

If you go to Options > Diagram, you’ll see a screen that shows your stats for playing each pair of characters.

The Diagram screen.

If you enter this sequence at that screen, you’ll hear a voice clip:

X, L, Z, L, X, Start, R, Y, X, Y.

After doing that, make your way to Survival Mode. Choose a character and hold down L while making your selection.

If you got it right, an animation test screen will appear.

Animation test with Aya Sakai.

A and B advance frames slowly, C rewinds frames slowly, R advances frames quickly, L rewinds frames quickly, and Start changes between attack and defense. The D-pad and X, Y, and Z change the displayed coordinates.


Technical details

I thought cheating at this game would be easy, because as soon as I figured out where it stores input and character unlock progress, I found this bit of code in the title screen routine:

if (
    (cheat_gate_060dc532 != 0) &&
    ((p1_held_060db6b0 & 0x8800) != 0) &&
    (characters_unlocked_060dc1c0 == 0)
) {
    characters_unlocked_060dc1c0 = 1;
    /* ... */
}

That is, you can unlock a character from the title screen if:

  • You haven’t already unlocked any characters.
  • You’re holding down L (0x0800) or R (0x8000).
  • The value at 060dc532 is nonzero.

I didn’t know how to make 060dc532 be nonzero, but tracing references to that address in Ghidra led to this code, which runs in a loop in the function at 06040158:

    if ((ABXZLX_code_[code_index] & p1_pressed_060db6d8) == 0) {
        code_index = 0;
    }
    else {
        code_index += 1;
        if (5 < code_index) {
            cheat_gate_060dc532 = 1;
            break;
        }
    }

This is a classic cheat code listener. There’s a sequence of buttons to press, and each match advances the sequence index. A mismatch resets it to zero.

OK, that’s easy, I thought. You have to enter a code on some screen. But which screen? I set an execution breakpoint for the cheat code listener’s function, and selected every menu item without getting any hits.

By working backward from the target function to the main menu code, I eventually determined that I’d have to get to the staff credits. That meant playing through Story mode. Rather than get good at the game, I located where the “end of match” state got triggered in the function at 0601717c:

    if ((p1_health_060dba92 < 0) || (p2_health_060dbbce < 0)) {
      match_state_060dbef8 = 5;
    }

So to win every match, I set player 2’s health to zero and delivered a final hit.

Things started going more smoothly from there: my breakpoint finally tripped on the credits screen. Entering A, B, X, Z, L, X set the 060dc532 value that was needed to unlock the first character at the title screen. I found that highlighting Options on the main menu and holding L+R and pressing B unlocked the second character.

But then I hit another snag. I could see that this code from the main menu routine unlocked the third character:

if (cheat_gate_060db6e1 == 0xf0) {
    gate_status = (cheat_gate_060db6e1 == 0xf0);
}
if (
    (characters_unlocked_060dc1c0 == 2) &&
    (gate_status == 1) &&
    (cheat_gate_060db6e1 != 0xf0)
) {
    characters_unlocked_060dc1c0 = 3;
    /* ... */
}

But I didn’t know how to make the value at 060db6e1 both match 0xf0 and then not match 0xf0. It was stuck at 0x00 in my testing.

I knew the target address had something to do with input, since pressing controller buttons changed the values in its neighborhood. I tried changing controller types – was the game looking for a Shuttle Mouse or something? Eventually I tried disconnecting Controller 2 entirely, and that gave me my 0xf0.

If I hadn’t spent so much time hunting for the credits screen, I would have missed the animation test code. Interestingly, I found a bug in the code that launches it. Here’s a simplified rendition of its logic:

if ((p1_held_060db6b0 & 0x800) != 0) {
    if (diagram_cheat_effect_060dc634 == 0) {
        return;
    }
    launch_animation_test_06019e0c();
}

That is, if you’re holding L after you select a character, the game checks whether you entered the code on the Diagram screen. If you did, it launches the animation test. But if you didn’t, it just bails out and you have to select a character again.

I wonder if the issue tracker for the game had a Holding L breaks Survival mode character select report marked as WONTFIX.


Outro

This isn’t the only game that makes you disconnect a controller as part of a cheat sequence:

I hope to discover more someday!

About the author

Bo Bayles

Rings of Saturn: 32bits.substack.com

Be the first to comment

Leave a comment

Your email address will not be published.


*