skip to main content

How Long To Beat That Game Boy Cartridge?

published icon  |  category icon programming

Last June, as part of a new course called Android App Development, our 2nd bachelor Engineering Technology students had to demonstrate their creative app development skills. As it was a new course—but a small one, at 3 ETCS points—I had to dig through Android and Kotlin docs to try to decide what to include and what to leave out. The end result is yet another Hugo-generated online course that is divided into two big parts:

  1. Language & support tools—A quick Kotlin 101 with ample examples from the Java world; how to TDD in the mobile world; a quick peek at multi-platform mobile development.
  2. Android essentials—the Android life cycle: activities; messaging between activities/apps: intents; typical layouts and their adapters: views; data storage options; complex layouting with fragments; listening to and processing hardware signals; security by design.

The Kotlin language is completely new for students, although Java shouldn’t be. Since 90% of all Stack Overflow Android searches yield Kotlin examples, and Google officially recommends Android developers to write in Kotlin, we decided to integrate that into the course as well. As an additional bonus, Kotlin now is also used in another course; Software Engineering Skills; in that same semester.

It’s quite a challenge to fit so many framework-heavy concepts into such as small course. The question becomes: what are we trying to teach students here? How to debug problems in case you’re stuck? How to efficiently look up information in API docs? It certainly wasn’t how to create accessible and easy-to-use mobile apps—the framework-fight was more than difficult enough.

I needed a cool example, something that would spark motivation and engage students in discovering what you could do with a mobile app. I came up with the How Long To Beat Android Demo App that incorporates everything the AppDev course has to offer, giving students a taste of what was possible within a (very) limited time frame using their newly acquired knowledge. It contains activities, a navigation drawer component, segments, RecyclerView lists, permissions and intents, multiple data storage implementations, and a few HTTPS API calls to demonstrate external data retrieval.

What does it do, you might wonder? Good question, here’s the answer:

In case that still wasn’t clear, the app:

  • … recognizes Game Boy and Game Boy Color cartridges based on a snapshot you take from your retro games;
  • … downloads art data and checks on how long it takes for an average player to beat the game;
  • … saves this information in your personal game database if selected;
  • … shows some basic statistics on your game completion progress.

Cartridges are “recognized” by using Google’s Vision API1 that returns OCR-recognized text from the uploaded camera snapshot. We’re interested in the so-called cartridge code on the left of the cart sticker that starts with DMG- (Dot Matrix Game) if it’s an old skool Game Boy cart and CGB- (Color Game Boy) if it’s a Game Boy Color cart. For example, here’s the Wario Land: Super Mario Land 3 cartridge:

The Wario Land cartridge that has 'DMG-WJ-USA' printed on sideways.

The Vision API will probably return something along the lines of "DMG-WJ-USA MADE IN JAPAN THIS SIDE OUT". The DMG-WJ-USA code uniquely identifies each GB game. Vision isn’t smart enough to detect the fancy lettering in the Wario Land logo, sadly.

Next, based on that code, the app searchers for the matching game title, either in a pre-defined repository (an embedded .csv file based on the database of Joonas Javanainen’s amazing Game Boy Hardware Database), or if it was not found, fires off a DuckDuckGo search to try and interpret its results as a game title. Note that there is no real DuckDuckGo API: the app employs HTML scraping, which will be probably broken by now.

Lastly, if a game title could be found, it is fed to—also using (admittedly a bit advanced) HTML scraping—to finally return the results in a list for a RecyclerView to display to the user. If at any step something goes wrong, a correct error message is displayed, and the user can retry the whole process. Since the MS acquisition, the HLTB REST API frequently changes, and I don’t think we’re supposed to “use” it this way, but hey, it’s just a demo.

Selecting a result from the HLTB results list automatically adds that game to your local database. You can “finish” the game by checking a checkbox in the game detail screen, meaning it took you x hours to finish. The statistics dialog box shows how long you still have to play to finish your entire collection.

It’s been a lot of fun to develop the app and I highly enjoyed writing in Kotlin compared to plain old Java. As for practical use: in reality, it’s obviously much quicker to simply surf to Some carts still aren’t recognized: the cartridge codes are region-dependent (hence the above -USA suffix), and in some regions, the middle part WJ changes, making predictions harder. Furthermore, it doesn’t support anything else besides GB and GBC games.

After scanning the Mario Golf GBC cart.

If you’re interested in the technical details, I segregated and released the demo project into another repository under the MIT license: The Vision API requiers a GoogleVisionApiKey in your that can be fetched from

  1. The easiest way to do this right now would probably be Android’s Text Recognition ML Kit that didn’t exist in 2021 when I started development of the project. This exposes the biggest problem with Android development: the API changes much too frequently. I was often confused, the docs weren’t up to date, answers posted online didn’t match with my library versions, … ↩︎

tags icon kotlin android

I'm Wouter Groeneveld, a Brain Baker, and I love the smell of freshly baked thoughts (and bread) in the morning. I sometimes convince others to bake their brain (and bread) too.

If you found this article amusing and/or helpful, you can support me via PayPal or Ko-Fi. I also like to hear your feedback via Mastodon or e-mail. Thanks!