screenshot

Naturally, you need to share your amazing Gameduino screenshots with the world at the highest possible quality.

No problem - the hardware has a built-in screenshot system. To use it, add a line like this in your code:

Serial.begin(1000000);
GD.screenshot(0);

here is the whole sketch:

#include <SPI.h>
#include <GD.h>

#define RED RGB(255,0,0)
#define GREEN RGB(0,255,0)

void setup()
{
  int i;

  GD.begin();
  GD.ascii();
  GD.putstr(20, 0, "Screenshot");

  GD.wr16(RAM_PAL + (8 * 127), RED);   // char 127: 0=red, 3=green
  GD.wr16(RAM_PAL + (8 * 127) + 6, GREEN);
  static PROGMEM prog_uchar box[] = {
     0xff, 0xff,
     0xc0, 0x03,
     0xc0, 0x03,
     0xc0, 0x03,
     0xc0, 0x03,
     0xc0, 0x03,
     0xc0, 0x03,
     0xff, 0xff };
  GD.copy(RAM_CHR + (16 * 127), box, sizeof(box));

  for (i = 0; i < 64; i++) {
    GD.wr(64 * i + i, 127);     // diagonal boxes

    char msg[20];
    sprintf(msg, "Line %d", i);
    GD.putstr(i + 2, i, msg);

    GD.wr(64 * i + 49, 127);    // boxes on right
  }

  Serial.begin(1000000);
  long started = millis();
  GD.screenshot(0);
}

void loop()
{
}

This will dump an image of the current screen to the host computer. Meanwhile on the host, have this Python script running on the Arduino's serial connection, as described in Arduino and Python:

#!/usr/bin/env python

import sys
import struct

import serial
import Image

def main():
    speed = 1000000
    im = Image.new("RGB", (400,300))
    pix = im.load()
    print "listening for screenshot on", sys.argv[1]
    ser = serial.Serial(sys.argv[1], speed)
    while True:
        s = ser.read(1)

        chk = ord(s)
        if chk != 0xa5:
            sys.stdout.write(s)
        else:
            (frame,) = struct.unpack("<H", ser.read(2))
            filename = "screenshot%05d.png" % frame
            for yi in range(300):
                (y,) = struct.unpack("H", ser.read(2))
                x = 0
                while x < 400:
                    (v,) = struct.unpack("H", ser.read(2))
                    if v & 0x8000:
                        for i in range(v & 0x7fff):
                            pix[x, y] = 0;
                            x += 1
                    else:
                        r = (v >> 10) & 31
                        g = (v >> 5) & 31
                        b = v & 31
                        pix[x, y] = (r * 8, g * 8, b * 8)
                        x += 1
            im.save(filename)
            print "captured screenshot to", filename

if __name__ == "__main__":
    main()

Launch your sketch, then run the script to collect the image from the serial line, e.g. /dev/ttyUSB0:

$ python screenshot.py /dev/ttyUSB0
listening for screenshot on /dev/ttyUSB0
captured screenshot to screenshot00000.png

the file screenshot00000.png will contain the 400x300 image from the Gameduino screen. Dumping a screenshot over USB takes about 3 seconds. You can create movies one frame at a time by giving incrementing numbers to GD.screenshot().

How does this all work? The Gameduino has a one-line RAM that captures the pixels sent to the video stream. Using the SCREENSHOT_Y register and SCREENSHOT RAM, the Arduino reads these pixels and sends them over the serial line. This is what GD.screenshot() does. A small script on the host computer reconstructs the screen image and saves it.