Pokémon Pinball: the world is your rumble pak!

tl;dr version of this page: you can get a ROM patch and instructions on how to use it from this Github repo!

Hey, remember Pokémon Pinball? This Game Boy Color game was released in 1999 with an unusual add-on: a Rumble Pak built into the cartridge. Powered by a single AAA cell, it provides haptic feedback when the ball hits walls or bumpers or gets saved from the alleys by Pikachu. According to Bulbapedia, it was the first Game Boy Color game with the rumble feature.

Image taken from some eBay listing. Those battery compartment lids have a habit of disappearing!

While I worked on a different project that utilized rumble, I began to wonder about Pokémon Pinball emulation. Do any emulators support Game Boy Color rumble? Would it be possible to wire up my own peripherals? I'd love to play Pokémon Pinball and transmit the rumble experience to someone else, for example.

Making sense of the cartridge

Enter PRET, the Pokémon Reverse Engineering Team. Their goal is to disassemble and make sense of the Pokémon games, starting from the game ROMs themselves. And they've already reverse-engineered Pokémon Pinball! I've consulted PRET, the Game Boy CPU manual, and the Pan Docs technical reference, but I'm still not 100% sure I understand this. What I think is happening is this:

Well, that explains why I couldn't find any correlation between the game's memory and the game's rumble status! But it still leaves us unable to detect rumble events. Fortunately, PRET provides detailed instructions on how to re-compile the game's assembly code into a playable ROM. I changed just one line of the assembly code to change the rumble trigger event. Now, instead of writing to bit 3 of 0x4000, it will write to bit 3 of 0xFF01 (a memory address we can read from!). The code re-compiled just fine and the ROM plays as expected. I was not expecting it to be that easy.

When the ball hits the bumper, address 0xFF01 changes from value 0xF7 to 0xFF, meaning the ROM hack is working!

Getting the game to trigger a thing

Now that the ROM is working, we need to write a script: something that checks the game's memory while we're playing to see if 0xFF01 has changed value, and activate our peripheral if it has. Lots of emulators support Lua scripts that do just that; streamers often use such tools for, say, updating an overlay with relevant stats, or indicating things like the player's inventory without having to open the inventory in-game.

My Lua script does not directly activate the peripheral; instead, it polls a webpage on a local server. This GET request is what actually turns on the rumble of the peripheral. To cut down on HTTP requests, I only check every twelfth frame (that is, every 200 milliseconds), which is roughly the minimum time the game rumbles for. I don't have a very good video of it yet, which is something I should work on soon.

Like I said at the top, you are welcome to try it yourself! Get the .ips patch and the Lua script from this Github repo and let me know what you would do with it!