Intercepting the Gameboy LCD

A peculiar aspect of the original Gameboy is how well it did given how absolutely dreadful the display hardware was. The screen is not backlit, the colour palette is a meager 4 shades of gray and the resolution is only 160×144 . Before you object that that’s just how the technology was back then, note that it launched at about the same time as the Lynx and the Game Gear,  both of which had beautiful backlit, 4096 colour screens.

(This site has moved to http://www.flashingleds.net, go there if you have comments or questions)

However the upshot of such a dismal screen is that the battery life is phenomenal, and this was instrumental in the Gameboy being such a spectacular success.  And when lots of big developers get involved, you get graphics that are actually pretty nice.

Brilliant pixel art in 4 shades

Twenty years later the hobby electronics scene is thriving and there is a wide variety of powerful, cheap hardware. You now have an army of people like me who are not embedded engineers, but have 20+MHz microcontrollers and a passionate desire to build stupid, pointless crap with them.

And those people may be interested to learn that because it’s so low-spec,  it’s quite straightforward to hijack the gameboy display for whatever nefarious purposes you please.

[EDIT: Based on some of the feedback I might not have made the point of this project perfectly clear. I’m not interested in re-using the screen (because the screen is terrible as discussed above). I want to access the video data from the gameboy so I can display it on something more interesting. You may of course do whatever you please with this information]

Let’s discuss how to go about this. A good source of information about the gameboy hardware is devrs.com. Particularly handy is the schematic by Jeff Frohwein:

Direct your attention to the “LCD Display” block on the left

The signals we are interested in are VERTSYN,HORSYNC, DATAOUT0, DATAOUT1 and CLOCK. These are the control lines for the LCD coming from the central processor (which is not shown in this schematic). I’ll explain how these control lines work in a moment. First we’ll discuss how to tap into them, which should enable us to reconstruct the images being sent to the LCD.

Just opening a Gameboy turns out to be one of the most difficult steps, thanks to stupid Nintendo and their stupid tri-wing screws. After several attempts with flathead screwdrivers I gave up and bought a triwing driver from ebay for a few bucks. Unless you’re happy to smash up the case, I suggest you do the same.

Once you do have it open, it’s not hard to find the signals we’re after with an oscilloscope or logic analyzer:

The LCD connector

Handily they’re 5V logic levels, but if your instrument does not have robust input protection then be careful of the -30V DC contrast signal! (I forget exactly which one, but it’s one of the lower 10 pins – use a multimeter to find it if you’re worried). The pitch is not particularly tight, so I simply soldered some ribbon cable to the LCD connector. It’s possible (but tight) to then feed this through the cart slot and still have access to the pins with the Gameboy closed up again.

With the gameboy on, this is the kind of data you’ll see:

Logic capture of one display line. This is too zoomed in to see any VSYNC pulses

Let’s discuss how these signal lines operate. The controller scans through each frame line by line, setting each pixel in sequence to whatever colour value is required. We start at the upper left of the screen, and start belting out pixel values.

The pixel clock pulses once for each pixel.  At the falling edge of the CLOCK signal, , DATA1 and DATA0 give you the 2-bit colour value corresponding to that pixel. You can see in the capture above that there is a large section of one colour in the middle of this line, where the colour value is 0b11.

Once all 160 pixels in the first horizontal line are done, we wait for a signal to move down and start the next line underneath. This is the role of the HSYNC line, and the signal is a rising edge.

Once 144 lines have been drawn, we wait for a signal to go back and start all over again with a new frame. This is the role of the VSYNC line, and the signal is a rising edge.

From the logic capture you can see that when a line is finished, the controller does not immediately start the next one. In fact over half the time assigned to each line is not used;  the pixel clock is not running. Specifically, we get 68.9us of deadtime after all 160 clock pulses before the next HSYNC pulse happens. After all 144 lines, we get 1.1ms before the next VSYNC pulse. This is not really an awful lot of time, so to do anything practical with this data you’ll probably be skipping some frames. Remember that 60Hz is the LCD refresh rate, but it’s not necessarily the speed at which the central processor is updating the screen.

As a proof of principle I exported a capture of the signal waveforms (with the excellent Saleae Logic) to my graphing software of choice (the excellent Igor Pro). After throwing together a very simple script to process the signals, we can indeed reconstruct the image!

Good grief, it worked!

If you’d like to play with this yourself, raw data from a frame (it’s not the same frame as the image above) and the Igor script are available below. Since WordPress apparently won’t let me post *.txt files, I have renamed them as doc files. I leave it “as an exercise for the reader” to change the file extension back if required.

Raw data

Igor script (be warned that it’s really something quick and dirty I threw together)

I have plans for this, and in a future post I’ll discuss doing something with it in (semi) real-time.

P.S. Of course I understand that you could get the same result, possibly a lot easier, with an emulator. But there’s just something pure about working with original hardware.

P.P.S. Navy Seals is an absolutely dreadful game. The other game I have on hand is Hook, which is even worse

[EDIT: Followup post here]

[EDIT (30/12/2011): If you came looking for gameboy hardware info, another great resource is this report by John Ernberg]

About Craig
Craig is getting towards the end of a PhD in experimental nanotechnology. Arguably he might be finished by now if it weren't for all the crap described on this blog. Queries/comments to flashingleds@gmail.com

23 Responses to Intercepting the Gameboy LCD

  1. Pingback: Diving deep into the Game Boy LCD protocol - Hack a Day

  2. Pingback: [dot]EXE » Diving deep into the Game Boy LCD protocol

  3. fermicissus says:

    what kind of oscilloscope or logic analyzer are you using for this?

    fun project btw

  4. John D says:

    Hey boss. I’m working on a similar project, and I was really amazed when I saw this on hackaday, because I’ve been stressing over it for awhile, and I don’t have a logic analyzer. I was wondering if you had any advice on this.
    I’m working with a screen out of a Gameboy Color, and I’m trying to make pretty images appear on it. It’s turning out to be quite frustrating, because I cannot seem to find datasheets anywhere on the internet. I’ve actually been working with the one you have linked on this page.
    Anyway, since I can’t get my hands on a logic device, I’m planning to just use a bunch of oscilloscopes and try to decode for data, H and V, and clock, and attempt to recreate it using a bunch of signal generators to see if i can make it do fancy things.
    If you have any words of wisdom, I’d really appreciate an email or something.

    • Craig says:

      I was more interested in tapping the video line to use the video signal from the gameboy for some other purpose, not so I could re-use the screen (the original model has a terrible screen, after all). So no, I haven’t tried to drive the screen with a microcontroller (I’m assuming you plan to use a micro and not solely a signal generator??). If I were to try that, my approach to start out would probably be to leave the screen mostly connected to the rest of the gameboy (to avoid having to deal with things like the contrast voltage).

      Then I’d start with holding all the databits high and just trying to get the Hsync/Vsync/Clock lines right (you should (?) be able to do a fillscreen, draw horizontal lines, set a single pixel etc). Once that’s all happy you can worry about getting the data (i.e. colour) values right.

      An instrument that can record signals like a logic analyzer or digital scope would be extremely handy, but since the control lines at least are periodic and repetitive you should be able to debug them pretty easily with any old oscilloscope. Let me know how you get on, it sounds like an interesting project.

      • John D says:

        Thanks, will try. Your work here is quite helpful in mine. By the way, I’m an engineering/physics undergrad. I’d love to find a degree in nanotech, but nothing like that is offered anywhere near me.

        • Craig says:

          My experience is that undergraduate degrees geared specifically towards nanotechnology are bad news. You’re better off with a ‘normal’ physics degree and getting a reasonable grounding in a wider scope of topics. Save specialization for postgraduate level.

          • John D says:

            Good plan. Also, unrelated I suppose, but I’m having trouble duplicating your result with Igor pro. Is there some magic wonder trick to making it actually display the picture based on the waveform you have here, or do I need to define a matrix for it to display it on?
            Cause what I’m trying here is load your procedure, load your data, and then run procedure on data, and it gives me a missing wave error when I specify a name for the screenshot, and an expected comma error when I do not.

  5. Richard G says:

    Hi. Great project and nice work. I totally fall into this “have 20+MHz microcontrollers and a passionate desire to build stupid, pointless crap with them” category :) Cool to do new stuff with old hardware.

    Having a problem similar to John D though. Having downloaded and installed Igor Pro just to checkout your data I’ve managed to load your script (aka procedure) and dataset (aka wave) and also create the empty matrix with “Make/N=(160,144)/I/O Screenshot” and call the proc with “MakeFrame(Screenshot, D0, D1, CLOCK, HSYNC, VSYNC)” but I can’t seem to get it to graph the Screenshot matrix properly – any tips?

    (being deliberately verbose above, in case anyone else wants to try it)

    • Craig says:

      Hi Richard.

      I only ever intended the Igor script to be useful as psuedo-code. I’m supremely impressed that you not only downloaded a copy of Igor but also took the time to learn some syntax to try to get it working. In view of that, I feel obliged to be more helpful.

      Once you’ve opened up Igor,
      1) Data>Load waves>Load general text> (downloaded logic dump). Press “load”
      2) Windows>Procedure Windows>Procedure window> (paste in Igor script)
      3) Windows>Command window> type in “Make/N=(160,144)/I/O Screenshot”
      4) Still in the command window, type in “MakeFrame(Screenshot, D0,D1,CLOCK,HSYNC,VSYNC)”
      5) Windows>New>Image Plot> push “Do it”.
      6) Graph>Modify image appearance> change colour table to grays16. Push “do it”. Almost there
      7) Windows>Command window> type in “SetAxis left 144,0;SetAxis bottom 0,160″.

      You’ll notice there’s still some artifacts on the left and bottom edge; you can play around with the analysis script if you like to see if you can address that. But in any case the point is made that you can take the image data captured from the LCD lines and reconstruct the image. Now just port this process to a micro with an interesting display! I’m working on something along these lines, stay tuned…

  6. ben says:

    I’ve been hesitant to buy the more expensive, albeit more powerful, Intronix LogicPort, or the BitScope 500.. the Saleae Logic looks like the perfect price / performance compromise!

    I did have a question though, is the LCD controller (S890623?), external to the LCD and to the Arm?

    The reason I ask is I’m wondering where the video memory actually resides.. if it’s in the arm for example, and you aren’t interested in real-time, couldn’t you dump the video data out the uart/multiplayer port?

    • Craig says:

      Hi Ben. I’m not entirely sure that I follow your question. My understanding is that the S890623 code refers to the LCD screen alone. The CPU (which is not an ARM but something like an 8080) drives the screen without an external controller, but there is 8k of external video ram.

      With some wizardry you might be able to reprogram the main controller, but the merit of ‘spying’ on it as I describe here is that it’s a very simple, not very invasive approach.

      • ben says:

        Doh! I was thinking of the Gameboy Advance… which was has open gcc toolchains and programmable cartridges that make it easy to run custom code on the Arm7 on!

        Not sure if the same resources exist for the original Gameboy, but if it does, then I suppose the video dumping to the link port would be possible.

        How fast are you capturing video at? Or are your just wanting to do one frame?

        • Craig says:

          Ideally I’ll capture at 15FPS or higher, but it depends on well I can do with the processor speeds I have available. I imagine a 70+MHz arm would make short work of it, but I might have to get creative. Stay tuned.

  7. Conust says:

    Is a very well written post. Thanks for the information posted. Sorry for my English

  8. good one. nice and goos site

  9. STONEDEAD says:

    WICH ONE CONTROLS THE HORIZONTAL PIXELS? ANYONE KNOW I HAVE INVISIBLE PIXELS ON MY GAMEBOY LCD SCREEN

  10. Pingback: Nindendoscope : Jouer à la Gameboy sur un oscilloscope | Semageek

  11. Anonymous says:

    wonderfull info. i am trying to put a gameboy advance in to a v.tech v.smile pocket case. 2 reasons i need something bigger to fit my hands and i want a bigger screen. The v.smle uses a backlit 4″ lcd. i have access to an o-scope and multimeters. but i have no idea where to start. any advise. i will have to manually wire the lcd to the gameboy because the ribbon cables are two different sizes..

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

Follow

Get every new post delivered to your Inbox.