39 comments

[ 3.9 ms ] story [ 89.5 ms ] thread
The art of living within a Vblank. Really cool read :) !

I assume A Link to the Past engine worked a lot like that too.

This was a great read. I’ve been writing a Game Boy emulator for fun recently and this really helps explain how developers “put the parts together” to handle some of the hardware limitations and get such a great and complex (relative to early games) result.

Does anyone know of breakdowns like this for other GB games, or at least parts of them?

Note the article contains links to two more specific blog posts on how the rendering loop works and how the game manages playfield tile sets to avoid corrupted graphics. Both are great reads too, don’t miss ‘em.

> Does anyone know of breakdowns like this for other GB games, or at least parts of them?

I don't know any, but you may enjoy "I am error", a very technical book about the Nintendo (NES) console and its software. It also included a (again, technical) 45+ pages chapter mainly focused on Mario.

(comment deleted)
This was a fascinating read. I hope the documentation will get filled out some more over time.
Link's Awakening is such a weird but fascinating entry in the Zelda series. I was not surprised to learn that its story was directly influenced by Twin Peaks.
Author here! Most of the engine documentation was figured out by many romhackers over the years; I merely started the efforts to write a comprehensive overview.

If you're interested in projects taking advantage of this knowledge, the Daid's LADX Randomizer [0] is awesome. It includes a ton of assembly tweaks that makes the engine more flexible, and add many options to the game.

And Link’s Awakening Redux [1] is a good example of life-improvement game tweaks made using the disassembly.

[0] LADXR: https://daid.github.io/LADXR/ [1] Link’s Awakening Redux: https://github.com/ShadowOne333/Links-Awakening-Redux

What was censored and what was the untranslated present?
I've been working on a project on top of LADXR, many thanks to all involved.
Nice. I wonder if they'd be willing to fix the bug where pressing left and right on the d-pad at the same time renders Link's sprite invisible. Not an issue on original hardware but quite dangerous when emulating.
Given that original hardware prevented that, I’m surprised it wouldn’t be a default-on option in emulator frontends.
Oh that’s neat. I’m struggling to think of bug prevention that’s similar on a PC. Orientation lock maybe?
The original hardware prevented it in the sense it's impossible to push both the left and right button at the same time on the Gameboy dpad, not through any software means.
Yes, I understood that it was "hardware" as in a fundamental constraint of the physical controller, but appreciate the clarification.

Certainly if it had been enforced by the console firmware, then it would be a no-brainer that emulators should do it.

Funny story about this actually is that a while ago I was retrofitting an old dance mat to be an XInput device via a Teensy, and I ran into a constraint where XInput's d-pad support only allowed one direction to be set at once, which obviously doesn't work for that use case. I ended up giving up and having the Teensy emulate a USB keyboard instead. (This was for use with Stepmania and Necrodancer on PC.)

Games of that era tended to hit the hardware directly for I/O, meaning that there is no firmware that can enforce any such thing. AFAIK the Game Boy boot ROM just verifies the Nintendo logo data, plays the chime, then boots the game, and after the game boots, the boot ROM completely disappears from the memory map.
Nintendo held onto this no os approach into the Wii era. Hence if you ran a japanese version game on a north American Wii you got the japanese Wii pause menu.

Meanwhile the PS3 and Xbox 360 had hypervisors.

Yeah, I remember that too— each game was shipping its own instance of the pause menu, so they would have subtly different behaviour, including around weird things like what the light on the disk drive did.

I imagine this kind of thing is also why the backcompat story for playing Wii games on a Wii U is so janky— you have to access them through the "vWii" environment, which I guess is basically just a kind of VM, so that it can provide a virtualized instance of the hardware that the game ROMs/discs are expecting to talk to.

Well, the Wii did have an OS, that would receive updates over time. IOS was managed sort of shitty, though. Since older games would be linked with specific versions of IOS, they had to literally keep multiple versions of the OS around on NAND. They would occasionally stub out specific slots (usually those used by the System Menu, or by internal-only discs, or even slots they never used but that pirates did use).

Agreed, however, that all PPC code running during a game came from code on the disc, even "OS" things like the Home menu. The IOS code largely gatekept the advanced Wii features as compared to the GC

It depends on the emulator, across pretty much every platform that uses a joystick or d-pad, but in my experience the default most commonly is no left+right input at the same time. (It's semantics as to whether the implementation is "allow left+right input" defaulted to off, or "prevent left+right input" defaulted to on.)
I'd also be interested to know what ends up happening if there are simultaneous presses— I assume last-one-wins would be the least surprising strategy for resolving it, but certainly several options are possible, and what is preferred might even be game-dependent.
This reminds me vaguely of the Sega Dreamcast controllers.

If I remember correctly, there is a hardware and software difference between pushing up on the joystick. Edit: Or rather some games depended on some analog noise(?) that is now filtered out by modern interfaces.

It doesn’t represent `{ x: 0, y: 1 }’, but I can’t remember if that was the case because of the physical joystick, which was then remapped in software, or some other case, though I assume that’s why.[1][2]

[1]: https://github.com/p1pkin/demul/issues/392

[2]: https://github.com/flyinghead/flycast/issues/287

I've never played this game on an emulator. That's pretty interesting. I need to find a ROM now.
I like the ratio - many liked it, not many had much to say.
(comment deleted)
Link's Awakening was my favorite GB game together with Pokémon Blue. What a memories!

It's awesome to have those documentation so many years later.

Very cool article!

If you want to know more about the hardware side of the Game Boy (Color), have a look at the Pan Docs: https://gbdev.io/pandocs/

It's been revamped in the recent years, in terms of presentation. I do kind of miss the old version which had a refreshing "old-school" UI like the RFCs of the IETF, but the newest version is IMHO much more usable when developing an emulator.

> Which means that by design, a “Keep current” section can only use the tiles shared by the adjacent tilesets, in that case the Tilesets A and B. If this rule is not honored, the graphics of the “Keep current” section will be corrupted.

Semi-related, in LTTP, is this related to the corrupted graphics after performing Death Mountain Descent (performing a glitched room transition between two normally disjoint areas of the dark world map)?

Kind-of.

The basic idea of needing to be able to display both screens with the same tileset during screen transitions does exist.

The game has a common section, and a section that can vary by screen. However most screens just use the common section, with only some screens using the unique section. Between any two unique sections the game will have at least one screen that does not use that section of the tilemap.

On screen transition, if the transitioned to screen needs a unique section, it is loaded, and then the screen starts to scroll. However the game will correctly handle going directly from one screen that uses the unique section to another. The only issue is that the old screen may look weird between when the new section is loaded, and scrolling has finished.

So what is happening with death mountain ascent/descent? Well, the death mountain area actually uses a modified version of the global tileset. (And modified versions of certain global palette entries). Normally it is not possible to go from the rest of the overworld to death mountain or vice versa, except via a cave (and switching from underworld to overworld requires reloading the tilesets), or via flute (where the same occurs).

The game lacks any code to modify the global part of the overworld tileset (and palettes) on a normal screen scroll transition, as that is never supposed to be needed in normal gameplay.

(There are similar considerations about what enemies can appear on adjacent screens, due to needing to manage sprite tilesets.)

Just chiming in - my absolute favorite GB game growing up. Fantastic storyline, amazing music, fun secrets. One of the best ever made for the system without a doubt.
This is some really nice documentation, and in one spot rather than strewn about. Major props for consolidating the information here!

In contrast, Ocarina of Time has been thoroughly torn apart, but the documentation isn't centralized anywhere. A lot of it has ended up in pastebins and shared through discord servers. I do worry that a lot of the knowledge will be lost once reversing the game is less in-vogue.

An example of this is that someone read through the assembly of how the fishing minigame works, which has many dependent variables. Various factors affect how quickly you can catch a fish, and which size you will catch. Speedrunners have abused this information to make the fishing minigame as 'easy' as possible despite it being based on random chance. It's a really fascinating read[0][1]... too bad it will eventually be lost to the sands of time.

[0] https://pastebin.com/WQrpxRCM

[1] https://pastebin.com/tsWjERR5

I used to wonder if the old game boy Zelda’s and Pokémon shared any code, my guess is probably not.

On that topic, Metroid Fusion supposedly uses the Warrior Land 4 engine

https://youtu.be/1ZyD9Z3jYfA

(comment deleted)