Introducing gbfs-web: attach files to homebrew ROMs without CLI tools

The Game Boy Advance and Nintendo DS homebrew scenes are amazing. Full stop.

One of the stars of that particular galaxy I leveraged for 4-e was Damian Yerrick's GBFS, a set of tools that pack files up into an archive that can then be concatenated onto the end of a ROM, and a library to compile into that ROM that can work with those files.

4-e uses this to let you attach your own set of e-Card .bin files to the ROM that I build and release, yielding a custom 4-e build without having to compile any of 4-e's code or—indeed—install devkitARM at all. (4-e has also gained a few new features since last week. Did you notice "set of files"? That's one. It's also a bit easier to use. Get a new version if you're still on the original.)

But after building 4-e, I wondered if I could make that process even easier. And, in a much shorter period of time than it took to reverse-engineer the e-Reader process for Super Mario Advance 4 and build 4-e, I made gbfs-web.

gbfs-web's job is really simple: you give it a ROM (and it should be easy to make a custom version that comes with the ROM already loaded), you give it one or more files, and it gives you a new ROM with the files loaded up as if you used the GBFS tools and concatenated the resulting archive. It does all this without uploading or downloading any ROMs or data files to any servers—it's all done inside your browser.

It does, at least in its initial version, deviate from what the original tools do just a bit. There was some inexplicable padding on each of the files in the archive that didn't seem to be serving a purpose, so I just skipped it. There's also "padbin" from the original tools that I do use when building 4-e, so the GBFS archive gets concatenated in a spot where it'll be easily found; gbfs-web doesn't take responsibility for that. It could do both of these things fairly easily, if needed.

Building it was a bit of a journey. I had previously done some work with packed binary data in JavaScript (TypeScript, actually) for a project at work, but that was a full-up Electron app and I was able to use Node.js Buffers, which have a pretty straightforward API for this sort of stuff. You have a Buffer, and you have a bunch of methods on it to stuff and unstuff data:

const buffer = Buffer.alloc(16);

// value=1000, offset=0
buffer.writeUInt16LE(1000, 0);

// offset=0
// length=undefined (auto-calculate)
// encoding
buffer.write("Some text", 4, undefined, "ascii");

And then, if that's not straightforward enough, if you're wondering what's in a Buffer, logging it shows you the bytes.

JavaScript… JavaScript enjoys pain.

const arrayBuffer = new ArrayBuffer(16);

const view = new DataView(arrayBuffer);
view.set.setUint16(0, 1000, true); // true means LE

const text = "Some text";
const chars = new Uint8Array(arrayBuffer, 4);
for (let i = 0; i < text.length; i++) {
    chars[i] = text.charCodeAt(i);
}

Arriving at even this was doubly infuriating, because in my first pass, I figured "an ArrayBuffer is an array of bytes… I can write bytes, right?" and so, in that loop, I did exactly that. The result in the console showed the string's bytes but the DataView writes seemed to do nothing, and when I then took the ArrayBuffer over to a Blob to save it, I got a file that had zeros in the string section but had the DataView int writes.

Turns out, you don't write to ArrayBuffers (which I missed when reading the docs originally.) Even though JavaScript lets you think you can by letting you assign values to subscripts of it. That's why I needed the UInt8Array. I guess an ArrayBuffer is more of a handle? I still passed all the ArrayBuffers that made up the ROM and GBFS file together to make the Blob and, in turn, the file… long story short, it works, but wow was that a lot.

Anyway, the result is still great. gbfs-web works out great for building a 4-e ROM. It would be at least possible to refactor bits of it out to create a JavaScript CLI version of the gbfs tool, though with a working tool shipping with devkitARM, I'm not hot to do that. gbfs-web does what it does and I'm happy that it can contribute to making 4-e—and other GBFS-using homebrew—even easier to get into.


You'll only receive email when they publish something new.

More from Mattie B
All posts