In this edition:
There’s a demo disc for Aerowings that lets you play a limited subset of the game.
It’s from a pre-final version of the game, built two weeks before the final release.
I’ve patched out the demo restrictions to allow exploration of this prototype build.
Get the patch from SegaXtreme! Below are the reverse engineering details that led to the patch, plus some observations on how this version differs from the final one.
Intro
The AeroWings series of flight sim games has more entries than you might guess. There were six releases for Dreamcast (including some expanded editions) and three demo discs.
Today we’re looking at a demo disc for the first game, Aero Dancing featuring Blue Impulse Tentou Taikenban. It normally lets you:
Watch one of the Blue Impulse Mission training exercises.
Play one of the Sky Mission Attack missions with a single plane
Play several of the Free Flight maps with two planes
The files on the disc are dated 1999-01-15, two weeks before the final game’s (1999-02-01). It has a nearly complete set of files, so it’s a good candidate for patching. Let’s try it!
The Mode Select screen
The demo disc skips the screen where you enter your name, so after the title screen you go straight to the Mode Select screen. It has the Multi Play; Option, and Library items marked as non-selectable.
By using the RALibretro emulator’s Memory Inspector, I found that your Mode Select entry is stored at address 0c408b8c
. The technique is:
Highlight the top item and filter for addresses with a value of
00
.Move down to the next item and filter for the set of addresses than have changed to
01
.Repeat with
02
,03
, etc.
Using Ghidra to analyze a memory snapshot (exported from Memory Inspector), I traced the references to that address to a function at 0c21b2f0
. The decompilation has a section that looks like this:
if (
(mode_select_cursor != 4) and
(mode_select_cursor != 3) and
(mode_select_cursor != 5)
):
# Do stuff
Suspicious! We can patch out those checks by replacing the branch instructions with null ops:
0c21b32c 0900 # Don't branch for mode 04
0c21b334 0900 # Don't branch for mode 03
0c21b33c 0900 # Don't branch for mode 05
This works; the other modes become selectable with these changes.
Accessing Exhibition mode
The final game has an unlockable Exhibition mode. Is it in this prerelease demo?
Looking at the mode select handler function again, another section stands out:
mode_select_cursor += 1
if mode_select_cursor > SOME_VALUE:
mode_select_cursor = SOME_OTHER_VALUE
That is, if the mode select cursor increments past SOME_VALUE
, it gets reset to SOME_OTHER_VALUE
. The first unknown is stored at 0c408b9c
, and its set to 5
— so it’s the limit for the number of modes.
Ghidra can trace writes to that address to a function at 0c21b2bc
, which has a section that looks like:
if SOME_FLAG & 0x01 == 0:
mode_select_limit = 5
else:
mode_select_limit = 6
SOME_FLAG
is stored at 0c010698
. We could simply change the 5
to a 6
with a patch, but this wouldn’t affect the other things that read this address. This patch changes the read into a write, which will persist:
0c21b2cc 01e0 # Load a 1 into r0
0c21b2cc 0222 # Store r1's value at the address in r2
0c21b2d0 0900 # Null operation
Now Exhibition mode is available:
Special options
The final game has a special effect that’s unlocked by entering your name as TASCAS (see, e.g. GameFAQs). Is that there on the demo?
The string TASCAS
does exist — it’s stored at 0c28eed4
. Ghidra finds one read to it, in the function at 0c21e30c
. It looks like this:
if SOME_FUNCTION(SOME_POINTER, "TASCAS") == 0:
SOME_FLAG = 0x01
SOME_FUNCTION
looks like a string comparison wrapper. SOME_FLAG
is stored at 0c28eed4
. But Ghidra doesn’t find any reads for this address. What happens if we set it anyway?
Answer: nothing! Ghidra is right; the special options aren’t present in this pre-release version of the game. Here’s what the special options look like in the final game:
In that version the enable flag lives at 0c257498
.
Free Flight maps
The Free Flight mode demo is pretty generous in that it lets you access eight maps. But are the other ones playable?
The cursor tracking trick above (highlight the first item and filter for memory addresses with 00
, highlight the next item and filter for addresses with 01
, etc.) reveals that the currently-selected map is stored at 0c2cf6ec
. That address doesn’t have any direct references, per Ghidra. But it seems to be part of a block that has several references in the function at 0c210524
.
That function has a big switch statement. The first case calls another function (at 0c20f108
) with an argument of 0c2cf680
. That’s this second function’s only call, so if we tell Ghidra that (Ctrl
+R
to set register r4
, the conventional first argument for SuperH calls), it will show us useful addresses.
One such useful address that pops up is 0c2cf6ec
, our currently selected map from above. The code looks like this:
SOME_FLAGS |= 0xbf
map_selected = 0x01
SOME_FUNCTION(SOME_POINTER, 10, 0xbf)
Hmm, 0xbf
has seven bits set, but what if we set more? Here’s my patch:
0c20f282 ffe0 # Store -1 (signed) in r0
This enables the Festival and Moon Light maps:
Free Flight planes
Similar techniques reveal that your “selected plane” value is stored at 0c2cf6e8
and that the same function (at 0c20f108
) responsible for map setup is responsible for plane setup. That function has a loop that looks like this:
for i in range(0xd):
if SOME_TABLE[i * 0x10] == 1:
set_bit(SOME_FLAGS, i)
if SOME_NUMBER == 1:
plane_selected = 1
elif SOME_NUMBER == 2:
plane_selected = 8
SOME_NUMBER
turns out to be the game type (Free Flight is 2
), and SOME_TABLE
turns out to include data on which planes are unlocked (the RetroAchievements people have this documented already for the final game, but here the addresses are shifted a bit).
We can make the table read always return a 1
with this patch:
0c20f226 01e0 # Read a constant 1
That does the trick — more planes become visible. You can see the bonus Dolphin and Buggy “planes” in the list:
However, you still can’t select them — there’s more to do.
The function at 0c210524
mentioned above is implicated again. It had the big switch statement, and case 0
contained the logic we modified above for unlocking maps and planes. It turns out case 1
has the logic for plane selection.
Following that to the function at 0c20f7ea
, we see something like:
if game_mode == 2:
if (plane_selected == 0x05) or (plane_selected == 0x08):
return 1
elif game_mode == 1:
if plane_selected == 0x00:
return 1
return 0
It’s simple enough to take out the conditionals such that the function always returns 1
:
0c20f836 1800 # Set true for every comparison
0c20f854 1800 # Ditto
0c20f84c 1800 # Ditto
Now every plane can be selected.
The other modes
The Sky Mission Attack mode doesn’t seem to have anything but the first mission implemented. You can change which one is selected with memory editing, and it will show you the briefing screen for that mission, but it always puts you into the first map anyway:
The memory editing trick works on the final version of the game, so I’m guessing that this is something that got finished in the last weeks of development.
Incidentally, some of the briefing screens got tweaked between this version and the final also — the spelling of “Valley” got corrected, for example:
The Blue Impulse Mission mode can’t really be unlocked without adding in a bunch of code — the function that handles user input (at 0c1e57b0
) lacks the handling logic for the D-pad buttons. In the demo it looks like this:
if pressed_button & B_BUTTON != 0:
return -1
if pressed_button & (A_BUTTON | START_BUTTON) != 0:
return 1
if pressed_button & (LEFT_BUTTON | RIGHT_BUTTON) != 0:
return 0
The final version has a bunch of cursor manipulation code. There’s no room to put it in, alas.
Multi-play works as a result of the patches above. You need a second player to start the mode, of course:
The Options screen is slightly different in the demo build. The fonts don’t quite match with the final version, and some screens are unfinished. Here’s a comparison of the Save/Load screens — the Controller and VMU icons aren’t in the demo:
Outro
If you’re a real AeroWings fan, get in touch! I’m sure there are more things about this pre-release build that are different from the final game.
I put more of the “reverse engineering journey” in this article. Good, or too much detail? Tell me in the comments.

“or too much detail?” - keep up the good work writing articles for release versions of games DC, it's awesome. I don't understand Ghidra, Python, reverse engineering, but I find it very interesting to read.
I haven't played Aero Dancing featuring Blue Impulse, have you tried entering the password: ?RADI CON!