jrra's zone

Pokemon Stadium 2

Updated September 10, 2019

I played this game to death as a kid. Let's find out what's inside!

Background

Pokemon Stadium 2 is a 64 MB ROM image. As typical for N64 games, there's no filesystem and no obvious structure on the inside. We know that the initial program is going to start roughly at the beginning of the ROM, and be at most one megabyte in size; any more than that, and an intermediate bootloader would be necessary.

On bootup, the N64 will copy the first megabyte of ROM (after the header) into RAM and execute it. So, we at least know where the entry point is. We'll have to dig into it with IDA later. But first, let's look for any clues to the ROM structure.

In a typical (sane) computer system, you'll have some sort of filesystem that lets you find individual chunks of data. You might find a directory called "graphics", and if you're not interested in graphical stuff, we can skip looking through all the files in that directory. On N64 we're not so lucky: most games have no filesystem (although there are a small number of exceptions). Instead, during the build process of an N64 game, the raw address of all assets in the game are available at link time. Game code always knows where a needed asset is in ROM without looking up its location in a filesystem.

We need to find structure. Let's get digging.

First attempt: binwalk

Binwalk is a great tool for looking at firmware images, but when it comes to video games, it's basically useless. Let's try it anyway.

$ binwalk np3e0.z64

DECIMAL       HEXADECIMAL     DESCRIPTION
--------------------------------------------------------------------------------
663884        0xA214C         Gameboy ROM,,[SGB], [ROM+MBC1+RAM+BATT], ROM: 256Kbit
2906713       0x2C5A59        Certificate in DER format (x509 v3), header length: 4, sequence length: 19587
19554941      0x12A627D       StuffIt Deluxe Segment (data): fgpD3#
22647968      0x15994A0       Gameboy ROM,, [ROM ONLY], ROM: 256Kbit
22648304      0x15995F0       Gameboy ROM,, [ROM ONLY], ROM: 256Kbit
22649118      0x159991E       MySQL MISAM index file Version 7
22738337      0x15AF5A1       MySQL MISAM index file Version 11
22739735      0x15AFB17       MySQL MISAM index file Version 9
22742911      0x15B077F       MySQL MISAM index file Version 7
26992350      0x19BDEDE       Certificate in DER format (x509 v3), header length: 4, sequence length: 9968
30877890      0x1D728C2       TROC filesystem, 1398099785 file entries
31021156      0x1D95864       LANCOM OEM file
31315505      0x1DDD631       Neighborly text, "neighborhood.>Ha, ha... Here's #26!"
31340945      0x1DE3991       Neighborly text, "neighborhood.>Ha, ha... Here's #26!"
31503361      0x1E0B401       Neighborly text, "neighborhood.>Ha, ha... Here's #26!"
31528721      0x1E11711       Neighborly text, "neighborhood.>Ha, ha... Here's #26!"
37472899      0x23BCA83       MySQL MISAM compressed data file Version 3
37482738      0x23BF0F2       MySQL MISAM compressed data file Version 3
37483991      0x23BF5D7       MySQL MISAM compressed data file Version 3
37490213      0x23C0E25       MySQL MISAM compressed data file Version 3
37502327      0x23C3D77       MySQL MISAM compressed data file Version 3
37502508      0x23C3E2C       MySQL MISAM index file Version 1
37597623      0x23DB1B7       MySQL MISAM compressed data file Version 3
38399368      0x249ED88       MySQL MISAM compressed data file Version 7
38483462      0x24B3606       MySQL MISAM index file Version 1
38658728      0x24DE2A8       Unix path: /01/CGB-BXTJ/exchange/index.txt
38737416      0x24F1608       MySQL MISAM index file Version 3
39120016      0x254EC90       MySQL ISAM index file Version 5
46057099      0x2BEC68B       Unix path: /E/5/0o5/5/e/
47451318      0x2D40CB6       MySQL ISAM compressed data file Version 11

This is overall pretty hopeless. Let's go over the results:

Binwalk was a waste of time, as expected. Moving on...

Second attempt: strings

The 'strings' program will walk a file and find any printable strings over a certain length. If we're lucky, we'll be able to find some landmarks in our ROM. The full output of 'strings' is enormous, but I'll point out some useful bits that I found.

We start off with the game name and product code, which are part of the ROM header:

$ strings -tx np3e0.z64
     20 POKEMON STADIUM 2   
     3b NP3E
 [...]

There's some text for displaying the contents of registers. This same text is found in many of Nintendo's N64 games, and is typically used when the game crashes:

 [...]
  a2744 THREAD:%d  (%s)
  a2754 PC:%08XH   SR:%08XH   VA:%08XH
  a2774 AT:%08XH   V0:%08XH   V1:%08XH
  a2794 A0:%08XH   A1:%08XH   A2:%08XH
  a27b4 A3:%08XH   T0:%08XH   T1:%08XH
  a27d4 T2:%08XH   T3:%08XH   T4:%08XH
  a27f4 T5:%08XH   T6:%08XH   T7:%08XH
  a2814 S0:%08XH   S1:%08XH   S2:%08XH
  a2834 S3:%08XH   S4:%08XH   S5:%08XH
  a2854 S6:%08XH   S7:%08XH   T8:%08XH
  a2874 T9:%08XH   GP:%08XH   SP:%08XH
  a2894 S8:%08XH   RA:%08XH
 [...]

The first few letters of all the Game Boy games that Pokemon Stadium 2 can interact with:

 [...]
  a55b0 POKEMON R
  a55bc POKEMON G
  a55c8 POKEMON B
  a55d4 POKEMON Y
  a55e0 POKEMON_G
  a55ec POKEMON_S
  a55f8 PM_CRYSTA
 [...]

Finally, something interesting! There's an RSP microcode string, found in all N64 games, immediately followed by the word "FRAGMENT":

 [...]
  a8738 RSP Gfx ucode F3DEX       fifo 2.08  Yoshitaka Yasumoto/Kawasedo 1999.
  a89cc 00@@
  a8a6d vjnjn
  a8a88 FRAGMENT
 [...]

A search through the strings output shows many more instances of "FRAGMENT":

$ strings -tx np3e0.z64 | grep FRAGMENT | head
  a8a88 FRAGMENT
  ad268 FRAGMENT
  adca8 FRAGMENT
  ae5e8 FRAGMENT
  b4d98 FRAGMENT
  b5da8 FRAGMENT
  ba238 FRAGMENT
  cc6b8 FRAGMENT
  d0488 FRAGMENT
  d4c38 FRAGMENT
 [...]

In total, strings found 762 instances of "FRAGMENT" in the ROM. Most of them are found at addresses that end with -8, such as the first match, a8a88. Looks interesting! Let's take a closer look.

Fragments

Here's what a fragment look like:

000a8a80: 08d4 0e46 0000 0000 4652 4147 4d45 4e54  ...F....FRAGMENT
000a8a90: 0000 0020 0000 3e80 0000 47e0 0000 40f0  ... ..>...G...@.
000a8aa0: 27bd ffd0 afbf 0014 afa5 0034 1480 0008  '..........4....
000a8ab0: 0080 3025 2404 0136 0000 2825 0c01 3264  ..0%$..6..(%..2d
000a8ac0: afa6 0030 3c01 8350 ac22 40dc 8fa6 0030  ...0<..P."@....0
000a8ad0: 2401 0005 14c1 002f 3c05 800d 24a5 0510  $....../<...$...
000a8ae0: 8ca3 0000 3c0f e700 3c19 fa00 246e 0008  ....<...<...$n..
000a8af0: acae 0000 ac6f 0000 ac60 0004 8ca3 0000  .....o...`......
000a8b00: 2409 0080 3c0b fcff 2478 0008 acb8 0000  $...<...$x......
000a8b10: ac79 0000 ac69 0004 8ca3 0000 3c0c fffc  .y...i......<...
 [...]

I came to the conclusion that these fragments are code modules. Each fragment carries a main function and relocation information. Fragments are structured like so:

struct fragment_s {
	uint32_t ep1, ep2;	// MIPS instructions to jump to the main function,
				// typically something like "j 0x8xx00020; nop"
	uint32_t magic1;	// "FRAG"
	uint32_t magic2;	// "MENT"
	uint32_t entrypoint;	// typically 0x20
	uint32_t relocations_offset;
	uint32_t size_in_rom;
	uint32_t size_in_ram;
	char data[];
};

Using the above struct, we can decode the fragment header:

		  .org 0x83500000
/* ep1 */	  j 0x83500020
/* ep2 */	  nop

/* magic1 */	  .word "FRAG"
/* magic2 */	  .word "MENT"

/* entrypoint */  .word 0x20	// offset from start of fragment
/* relocations */ .word 0x3e80	// ^^^
/* size_in_rom */ .word 0x47e0	// ^^^
/* size_in_ram */ .word 0x40f0	// ^^^

		  .org 0x83500020
/* data[] */	  addiu $sp, -0x30
		  sw $ra, 0x30+var_1C($sp)
		  sw $a1, 0x30+arg_4($sp)
		  bnez $a0, loc_83500050
		 [...code continues...]

The entrypoint in this example is 0x83500000. This address is not used in the N64 memory map. It turns out that each fragment is pre-linked to a bogus base address like this one. When a fragment is loaded, all address references are change to point to its new location in RAM.

There's another interesting thing about this entrypoint. Each code fragment is given a unique fragment number. This number is used to derive the base address. The formula is:

fragment_number = ((base_address & 0x0ff00000) >> 20) - 0x10;
base_address = 0x80000000 | ((fragment_number + 0x10) << 20);

So for example, if the base address is 0x83500000, then it's fragment number 0x25, or 37.

Debug Fragments

There are a bunch of unused fragments left in the game that were used for debugging. Let's take a look!

Fragment 224: Debug Menu

The Debug Menu takes you to the other fragments shown below. Actually, selecting any option here will simply kick you back out to whatever screen you came from, as the code to drive the menu appears to have been deleted.

Fragment 124: Clock Editor

The Clock Editor lets you set the clock of the Pokemon Gold, Silver, or Crystal game connected to Controller 1. These games have a real-time clock. Normally, the clock can be set only once when the game is first started, and never changed again, to prevent the player from time travelling. The Clock Editor bypasses this limitation to let you directly set the clock.

The "Break the clock" option will set the clock state to something invalid. If the Game Boy game is started while the clock is broken, it will detect this case and allow the player to reset the clock.

Fragment 125: Item Editor

The Item Editor is not a full-fledged editor. Instead, it fills the Color and Metal Cases (item storage areas) with items.

Fragment 225: Model Viewer

The Model Viewer is a full-fledged viewer of Pokemon models. It has a number of features:

Fragment 226: Screen Viewer

The Screen Viewer is used for showing the various pre-made screens used throughout the game, like the Stadium cup select screen, or the many info cards shown in the Classroom. Screens can be viewed in low-rez and high-rez. There are a few Mobile Stadium-related screens that are translated in the USA version of the game. Some screens will crash the game.

Fragment 227: Bakkutsukun

I think this is supposed to be the Backup Editor. It lets you toggle all the unlockables in the game, such as whether a certain cup has been beaten, or if the GB emulator speed boosts were won.

The "Mobile Stadium Appears" toggle is a left-over from the Japanese version of the game: in the Japanese version, the Mobile Stadium option will unlock once a Pokemon Crystal cartridge is inserted that has interacted with a GB Mobile Adapter. In the international versions, there is no way to make the Mobile Stadium menu option appear, and toggling this setting has no effect (although the setting is saved).

Fragment 228: Creating Icon

Pokemon icons are used as UI elements in many parts of Pokemon Stadium 2. This fragment lets you modify them.

Icons are stored in the ROM in two ways: first, as a set of coordinates used to position a Pokemon model inside a frame, and second, as a pre-rendered image. This tool lets you both change the coordinates, and re-render the images.

Fragment 229: Music Room

A simple music player.

Fragment 230: Trainer Viewer

Lets you view all of the Trainer headshots in both low-rez and high-rez.

Fragment 231: AI Editor

This is one of only two debug fragments that was not translated into English. I have shown a screenshot of both the USA and Japanese versions for comparison.

The AI Editor can tweak the many AI opponent profiles used in the game. For example, a profile can be made to not exploit a Pokemon type advantage, or to want to use items more often.

Fragment 232: PokeMon Editor

This tool lets you edit the Pokemon on the GB game pak inserted into Controller 1. Among the editable fields are:

There is a minor bug in this tool. A move will appear in red if the Pokemon cannot normally know that move. However, it flags the Dizzy Punch on my Elekid in red. Elekid can learn Dizzy Punch if it is hatched from the Odd Egg Please see my petition on Change.org to get this fixed.

Fragment 233: GB SRAM Editor

The GB SRAM Editor is a hex editor that operates on the SRAM of the Game Boy game pak attached to Controller 1. It works just like any common hex editor, with one difference: the text on the right side uses the peculiar character set of the Game Boy Pokemon games, rather than ASCII.

Fragment 234: Ogawa no Yu

This screen looks like it should toggle the various unlockables in the game, but none of the options have any noticeable effect.

Some text in the bottom left was not translated from Japanese: the top line should read 'Model', and the bottom line should read 'Animation'.

Fragment 235: Registered PokeMon Editor

This is similar to the 'PokeMon Editor' above, except that it lets you change the Pokemon contained in registered sets that are stored on the Pokemon Stadium 2 cartridge.

Fragment 236: Create Registrate POKeMON

I'm not too sure about this one. It seems to create some sort of battle record and save it to the GB game pak in Controller 1. In my testing, it only worked if that game pak was Pokemon Crystal. More research is needed!

Fragment 237: Message Debug

This tool lets you view any battle or trainer message in the game. It can also cycle through all battle or trainer messages. Unknown what "checks" it performs on the messages.

The End

I think there's a lot more to find in this game. I'll update this page as I find things!