Open Source Handhelds Workshop

Steve Maddison, April 2011

Introduction

The aim of this workshop is to give an insight into the process of porting and developing software for handheld platforms. This tutorial targets the Pandora, but the process is similar for other handheld devices.

The tutorial explains how to compile C/C++ source code into a binary and how to package that binary in PND format for use on the Pandora.

Prerequisites

SDK and Tool Chain Set-up

The following steps explain how to install and configure the SDK and cross-compiling tool chain. The SDK used here is slightly dated, but well suited to the workshop environment as it's quick to install and doesn't require downloading extra components from the Internet. For serious developers, a more up-to-date SDK is linked to at the end of the tutorial.

Unpack the Archive

The toolchain/SDK is supplied as a bzipped tar archive which needs to be unpacked to the root directory (i.e. "/"). Don't worry - the archive contains only the contents of /usr/local/angstrom/arm, so it's safe to do this (as root):

$ sudo tar -C / -xjf 20100611-i686-linux-armv7a-linux-gnueabi-toolchain-openpandora.tar.bz2

If you ever want to remove the SDK, simply delete the /usr/local/angstrom/arm directory.

Setting Permissions

If you're going to be adding stuff (e.g. libraries) to the SDK, it can be useful to give yourself write access to the new directory, e.g.

$ sudo chown -R user.group /usr/local/angstrom/arm

SDK Fixes

The provided SDK is not perfect: some minor changes will make your life a whole lot easier, especially for this tutorial. What we do next is change the paths returned by various configuration scripts. By default, these are set up to return /usr/include and /usr/lib, whist we need them to return the paths to the headers and libraries in our SDK. One way to do this would be:

$ cd /usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/bin
$ for i in *-config ; do \
>   sed -i 's|/usr/include|/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/include|g' $i ;
> done
$ for i in *-config ; do \
>   sed -i 's|/usr/lib|/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr/lib|g' $i ;
> done

The compiler itself requires libmprf, but is linked to version 1 of this library. You may have a newer version installed, but for our purposes the library is backwards compatible, so we can fudge it thus:

$ cd /usr/lib
$ sudo ln -s libmpfr.so.4.0.0 libmpfr.so.1

Environment and Aliases

The SDK includes a script which sets some environment variables and aliases to simplify use of the tool chain. This script needs to be included from the shell you're going to be compiling in, like this (and yes, the "." is part of the command):

. /usr/local/angstrom/arm/environment-setup

If you're going to be using it a lot, you might like to add this line to your shell's profile. This may however mess up any native compiler(s) you may have on your system, so for occasional cross-compiling you're better off including the file explicitly on a per-session basis.

Pre-Flight Check

At this point, you should be able to run the C compiler:

$ arm-angstrom-linux-gnueabi-gcc -v

You should be presented with a bunch of configuration information, followed by the compiler version. If instead you get an error message about GLIBC_2.11, you might like to try setting up an alternate tool chain.

Let's Build Something

Now, at this point we could compile something boring, like the venerable "Hello, World!" program. If that's your thing, a simple command will do (the writing of hello.c being left as an exercise for the reader):

$ arm-angstrom-linux-gnueabi-gcc -o hello hello.c

Instead, let's try building something a bit more useful, like the Nintendo Game Boy Advance emulator, VisualBoyAdvance (which also emulates the original Game Boy and Game Boy Color). This is a highly portable program, so it works without too much fuss on the Pandora. It also has the added benefit of introducing the typical approach for building software which comes with a GNU autotools configure script. Like a lot of software that makes its way to the Pandora, VBA uses the popular Simple DirectMedia Layer (a.k.a. SDL) library for graphics, sound and input handling.

Get the Source

First, we'll of course be needing the sources, which you can download here (1.4 MB). Unpack these somewhere, and cd to the source directory, e.g.:

$ tar xzf VisualBoyAdvance-src-1.7.2.tar.gz
$ cd VisualBoyAdvance-1.7.2

Configure the Build

Now, as you'd usually do, we run the configure script. However, unlike with a native build, we need to tell the script to use our cross-compiling tool chain, like this:

$ ./configure \
>   --prefix=$HOME/pandora/vba \
>   --host=arm-angstrom-linux-gnueabi \
>   --with-sdl-prefix=/usr/local/angstrom/arm/arm-angstrom-linux-gnueabi/usr

Let's break that down:

Compile and Install

When configure's done, it should have produced a bunch of Makefiles with which we can compile the program. Go ahead and type "make" at the command prompt to start the compilation process. Assuming this doesn't bomb out, follow up with "make install", which should copy the files we're interested in to the --prefix we specified before.

Making a PND Package

At this stage, if we'd never built this executable before, it would be advisable to test it on the target platform before going further. This way you don't waste time building a package for something that doesn't work, and you can work out a reasonable default configuration for your program.

However, in our case we can be reasonably sure the executable is OK and I'm going to provide you with a sane configuration file, so let's go ahead and package it into a PND.

Set Up a Directory

The first thing we need to do is collect all the files we need toegther so we can make an image of them for the package. Then we copy the executable and configuration file we just made into this directory. For example:

$ mkdir ~/pandora/pnd/vba-1.7.2
$ cd ~/pandora/pnd/vba-1.7.2
$ cp ~/pandora/vba/bin/* ~/pandora/vba/etc/* .

Writing a Start-Up Script

As we'll see later, the PND system doesn't allow us to pass command line options to our executable. Also, if the configuration file is part of the PND image, it will be read-only and the user won't be able to make changes. In order to make our configuration file writable, we need to create a copy which will be saved on the SD card. As if that wasn't enough, the executable we just built needs to be passed the name of the game we want to play when it's run, so we need a way of requesting a file name from the user.

The easiest way to do all these things is to write a simple script which does them for us. We then tell the PND system to run this script, instead of the executable itself. Here's a simple script we can use for our package. Copy the contents to a file named vba.sh in the same directory as the executable. Note the use of double quotes (") for the GAME variable, which allows us to handle file names containing spaces.

#!/bin/sh

# Check if the configuration file already exists...
if [ ! -f VisualBoyAdvance.cfg ] ; then
    # If not, copy the default to the SD card
    cp Default.cfg VisualBoyAdvance.cfg
fi

# Use the Zenity file picker to allow the user to select a game.
GAME="`zenity --file-selection --title='Select a File'`"

# Call the VBA executable, pointing to the writable configuration
# file and the game the user selected above.
./VisualBoyAdvance -c VisualBoyAdvance.cfg "$GAME"

Of course, for this to work we need to rename the configuration file in what will become our PND package, otherwise VisualBoyAdvance.cfg will already exist in the package and therefore remain read-only.

$ cd ~/pandora/pnd/vba-1.7.2
$ mv VisualBoyAdvance.cfg Default.cfg

Configuration

We need to change our default configuration to better suit the target device. Usually this requires a bit of trial and error which is better done before packaging, but for the purposes of the tutorial we can speed that up a bit by giving you the answers. Make the following changes in your new Default.cfg file:

Icons and Previews

If you're feeling creative, you might want to make an icon for your package. These must be in PNG format but can be pretty much any size, within reason. It's also possible to specify a preview image, such as a screen shot, which can be displayed in the Pandora's menu. Both these items are optional, but you can use this icon if you'd like.

Writing the PXML

The heart of the PND package is the PXML file. This describes the package and lets the system know how to execute our program. Considering one could write an entire workshop on this subject alone, just take my word for it that the following PXML is pretty much what we want and copy the contents into a file named PXML.xml in the directory with the rest of our stuff.

<?xml version="1.0"?>
<PXML xmlns="http://openpandora.org/namespaces/PXML">
 <package id="vba.workshop.001">
  <title lang="en_US">VisualBoyAdvance</title>
  <description lang="en_US">Nintendo Game Boy, Game Boy Color
    and Game Boy Advance emulator.</description>
  <author name="Your Name Here" website="http://www.example.com/"/>
  <version major="1" minor="7" release="2" build="0"/>
 </package>

 <application id="vba.workshop-1.7.2" appdata="vba.workshop">
  <title lang="en_US">VisualBoyAdvance</title>
  <description lang="en_US">Nintendo Game Boy, Game Boy Color
    and Game Boy Advance emulator.</description>
  <author name="Your Name Here" website="http://www.example.com/"/>
  <version major="1" minor="7" release="2" build="0"/>
  
  <exec command="vba.sh"/>
  <icon src="vba.png"/>
  
  <categories>
   <category name="Game">
    <subcategory name="Emulator"/>
   </category>
  </categories>
 </application>
</PXML>

Most of the PXML file here is pretty self-explanatory. We define a package containing one application with a unique identifier made up of the name and version number. For the data saved on SD card, we want to use the same directory for subsequent versions, so we also specify a more generic appdata directory for the application.

The title, description, author and version tags contain the obvious meteadata for our package/application. Next we specify the script we made (vba.sh) as our executable, and point to its icon.

Finally we tell the menu system where it should place this application. The categories follow the Free Desktop Specification. For more info on the PXML format, check out the PXML specification.

Making the Package

Now we have everything ready, it's time to make the actual PND. First thing we need is a file system image. This can be either an ISO or a SquashFS filesystem. SquashFS gives us the benefit of compressing the image and has negligible impact on read times, especially for packages containing only a handful of files.

There are scripts to simplify this process, but it's not that complicated, so we'll do it manually to see how it works.

$ cd ~/pandora/pnd
$ mksquashfs vba-1.7.2 vba-1.7.2.squash

This packs the directory containing all the files we just made into a SquashFS image named vba-1.7.2.squash. Next we need to append our PXML and (optionally) our icon to the image to create a PND.

$ cat vba-1.7.2.squash vba-1.7.2/PXML.xml vba-1.7.2/vba.png > vba-1.7.2.pnd

That's it - go try out your PND! If you run into trouble, the first place to look is the output of the PND system on the Pandora. This is written to the /tmp/pndrun* files, one named after each application.

Further Reading

This tutorial is just a brief introduction to developing for the Pandora. For more information, check out some of these resources:


©2011 Steve Maddison
Released under the GNU Free Documentation License.