Ubuntu 9.10 gets a clue!

I was pleasantly surprised to see that the latest version of Ubuntu, 9.10 b1, comes with a nice selection of desktop backgrounds. This makes a huge difference in how beginners perceive the product, at very little cost to Ubuntu. The new dark-brown default color scheme is also an improvement over the older schemes.

I published my first Android app

Now that the Android Native Development Kit has been released, I was finally able to publish the sources and binary to my Android Terminal Emulator. It’s a fairly plain Digital Equipment Corporation VT-100 terminal emulator, with some features from newer terminals (like colors.)

This is my first application in the Android Market. There are at least 10 other terminal emulators in the market; we’ll see how this one is received.

A bit of history: This was my first Android application. I wrote it for the original “Sooner” Android devices, and have kept it updated for the successive generations of devices. It requires native code because there’s no public Android Java APIs for dealing with PTYs.

A bit of ancient history: I wrote two terminal emulators for the Atari 800 back in the day: Chameleon, in 6502 assembly, and a version of Kermit in the excellent “Action!” programming language. Kermit was one of my first “open source” programs. If you poke around on the web you can still find it here and there.

GLES Quake - a port of Quake to the Android platform

I’ve just published the source code to a port of Quake to the Android platform. This is something I did a while ago as a internal test application.

It’s not very useful as a game, because there hasn’t been any attempt to optimize the controls for the mobile phone. It’s also awkward to install because the end user has to supply the Quake data files on their own.

Still, I thought people might enjoy seeing a full-sized example of how to write a native code video game for the Android platform. So there it is, in all its retro glory.

(Porting Quake II or Quake III is left as an exercise for the reader. :-)

What’s different about this particular port of Quake?

Converted the original application into a DLL

Android applications are written in Java, but they are allowed to call native languge DLLs, and the native language DLLs are allowed to call a limited selection of OS APIs, which include OpenGL ES and Linux File I/O.

I was able to make the game work by using Java for:

  • The Android activity life-cycle
  • Event input
  • View system integration
  • EGL initialization
  • Running the game in its own rendering loop, separate from the UI thread

And then I use C++ for the rest. The interface between Java and C is pretty simple. There are calls for:

  • initialize
  • step - which does a game step, and draws a new frame.
  • handle an input event (by setting variables that are read during the “step” call.)
  • quit

The Java-to-C API is a little hacky. At the time I developed this game I didn’t know very much about how to use JNI, so I didn’t implement any C-to- Java calls, preferring to pass status back in return values. For example the “step” function returns a trinary value indicating:

  1. That the game wants raw PC keyboard events, because it is in normal gameplay mode.
  2. That it wants ASCII character events, because it is in menu / console mode.
  3. That the user has chosen to Quit.

This might better have been handled by providing a series of Java methods that the C code could call back. (But using the return value was easier. :-))

Similarly, the “step” function takes arguments that give the current screen size. This is used to tell the game when the screen size has changed. It would be cleaner if this was communicated by a separate API call.

Converted the Quake code from C to C++

I did this early in development, because I’m more comfortable writing in C++ than in C. I like the ability to use classes occasionally. The game remains 99% pure C, since I didn’t rewrite very much of it. Also, as part of the general cleanup I fixed all gcc warnings. This was fairly easy to do, with the exception of aliasing warnings related to the “Quake C” interpreter FFI.

Converted the graphics from OpenGL to OpenGL ES

This was necessary to run on the Android platform. I did a straightforward port. The most difficult part of the port was implementing texture conversion routines that replicated OpenGL functionality not present in OpenGL ES. (Converting RGB textures to RGBA textures, synthesizing MIP-maps and so forth.)

Implemented a Texture Manager

The original glQuake game allocated textures as needed, never releasing old textures. It relied upon the OpenGL driver to manage the texture memory, which in turn relied on the Operating System’s virtual memory to store all the textures. But Android does not have enough RAM to store all the game’s textures at once, and the Android OS does not implement a swap system to offload RAM to the Flash or SD Card. I worked around this by implementing my own ad-hoc swap system. I wrote a texture manager that uses a memory mapped file (backed by a file on the SD Card) to store the textures, and maintained a limited size LRU cache of active textures in the OpenGL ES context.

Faking a PC Keyboard

Quake expects to talk to a PC keyboard as its primary input device. It handles raw key-down and key-up events, and handles the shift keys itself. This was a problem for Android because mobile phone devices have a much smaller keyboard. So a character like ‘[’ might be unshifted on a PC keyboard, but is shifted on the Android keyboard.

I solved this by translating Android keys into PC keys, and by rewriting the config.cfg file to use a different set of default keys to play the game. But my solution is not perfect, because it is essentially hard-coded to a particular Android device. (The T-Mobile G1). As Android devices proliferate there are likely to be new Android devices with alternate keyboard layouts, and they will not necessarily be able to control the game effectively using a G1-optimized control scheme.

A better approach would be to redesign the game control scheme to avoid needing keyboard input.

A Few Words about Debugging

I did the initial bring-up of Android Quake on a Macintosh, using XCode and a special build of Android called “the simulator”, which runs a limited version of the entire Android system as a native Mac OS application. This was helpful because I was able to use the XCode visual debugger to debug the game.

Once the game was limping along, I switched to debugging using “printf”-style log-based debugging and the emulator, and once T-Mobile G1 hardware became available I switched to using real hardware.

Using printf-style debugging was awkward, but sufficient for my needs. It would be very nice to have a source-level native code debugger that worked with Eclipse.

Note that the simulator and emulator use a software OpenGL ES implementation, which is slightly different than the hardware OpenGL ES implementation available on real Android devices. This required extra debugging and coding. It seems that every time Android Quake is ported to a new OpenGL ES implementation it exposes bugs in both the game’s use of OpenGL ES and the device’s OpenGL ES implementation.

Oh, and I sure wish I had a Microsoft PIX-style graphics debugger! It would have been very helpful during those head-scratching “why is the screen black” debugging sessions.

IDF 2009 Larrabee demo

Intel showed their new Larrabee GPU publicly for the first time at their annual developer conference. They showed Larrabee running a ray tracer that was rendering QuakeWars geometry. The enthusiast scene (e.g. beyond3d) was not impressed by this demo, because, frankly, it wasn’t very impressive at an emotional level. The scene was static, no people in it, just waves and a few very small helicopters. It’s strange that they didn’t even move the camera, which is something that a ray tracing engine should easily be able to to. The camera angle they chose was effective for showing dynamic reflections, but keeping the camera locked down meant a much less interesting demo. For the same amount of effort they could have come up with a much more visually and emotionally interesting demo. For example, a cascade of brightly colored chrome balls tumbling down a staircase, which would show off both physics and ray tracing. That they didn’t use this early opportunity to sell Larrabee indicates that they don’t know how to market add-on GPUs to consumers. Which makes sense, since it has been many years since they’ve needed to do this. Their current demos are all targeted to (a) test out Larrabee features, and (b) educate developers as to the potential strengths of Larrabee. They are similar to Microsoft DirectX samples. But I think Intal also needs to develop showy “AMD/ATI Ruby” style demos to win the hearts of enthusiasts. Groo at semiaccurate.com suggests that the IDF demo was shown on early, barely functional Larrabee silicon. If true, that could help explain why the demo was so limited. But by this time in the GPU’s lifecycle there should be more marketing – even if totally pre-rendered – showing what the GPU will do. So far the bland GDC2009 meteor demo is the only thing we’ve seen. I think Larrabee needs more sizzle, like this early Sony Playstation 2 demo reel. (Sony also had some great interactive tech demos of things like feathers and pollen particles, but I haven’t been able to find online videos in my limited searching.) Intel’s current marketing approach seems to indicate that they are not serious about competing for the enthusiast add-on GPU market. Perhaps they are just waiting until it’s closer to the time Larrabee is available for market, but my guess is that they just don’t understand how to play the game. It would be a shame if Larrabee is a technical success but a sales failure due to poor marketing execution.

Brick Break - a Javascript Breakout clone

Brick Break game screenshot

This weekend I wrote a Javascript clone of the old Atari “Breakout” game. Thanks to the “Canvas” tag it was very easy to write, but I did run into a few problems:

  • Javascript math is always floating point, so I had to use the “Math.floor” function to convert the results of a division to an integer. This was in the brick collision detection logic, where I am converting the ball’s (x,y) coordinates to the bricks that the ball might be hitting.

  • I was evaluating document.getElementById too early in the document lifecycle, before the corresponding elements existed. This took me a long time to diagnose – I ended up just moving the getElementById calls to their run-time use, rather than trying to cache the results.

Jack’s Brick Break Breakout clone

ICFP 2009 paper on Haskell in the Real World

Here’s a good paper on using Haskell to write a commercial application. The authors are practical commercial programmers who tried Haskell to see if it was a more effective language than Ruby: Experience Report: Haskell in the “Real World” Writing a Commercial Application in a Lazy Functional Language Of special interest is the “Problems and Disadvantages” section. It seems that space leaks which are a continuing source of trouble in the authors’ application. Reading this paper reminds me of Tenerife Skunkworks Haskell vs Erlang Reloaded. In that experiment a developer found that Erlang was much better than Haskell for real-time programming.

Back to gnome

Well, 8 hours using wmii was enough for me. Too many apps didn’t quite work right. So I’m back to plain-old-boring-but-familiar Gnome.

Technology Trends I'm Keeping an Eye On

In no particular order, here’s what I’ve been studying lately:

  • Javascript. I’ve avoided this language over the years because of its low speed and shoddy reputation. But the language implementations seem to be getting faster and the available libraries seem to be getting more interesting. I’ve just watched all of Doug Crockford’s YUI lectures on JavaScript, and I’m thinking about trying to use the language in some toy projects.
  • git gui - this git command, available in recent builds of git, make Git changes pretty easy to author.
  • The Undercover Economist - this is a great book about economic theory. It’s pretty easy to read while shaving, or waiting for compiles. Lots of good anecdotes and tools for modeling the behavior of consumers and firms. I took 3 economics classes in college, and they didn’t teach me as much practical information as I’ve learned from reading this book.
  • Hacker News - this link voting site has replaced alterslash and reddit programming as my daily comp-sci news site. I like the emphasis on start-up news.
  • wmii - yet another tiling window manager. I tried a bunch of tiling window managers, and this one seemed to “click” with me. I found that I could customize it easily, and it mostly “just worked” the way I wanted it to. We’ll see if I stick with it or go back to Gnome. [Follow-up. I went back to Gnome (and then to OSX). Oh well.]
  • Chrome - now that the Linux and OSX versions have Flash support, Chrome has become my default web browser. I like its clean UI.

Dual XHD7714 Road Trip Report

After a month of using the Dual XHD7714, during which my family and I took a 4000 mile road trip, I have to say it’s a pretty nice system. We used it almost exclusively as an MP3 player, rather than an HD Radio or a CD player. I loaded 800 songs from our home music collection onto an 8GB memory stick. It was great introducing my kids to some new music. By the end of the trip their favorite songs were Shock the Monkey and The Magical Mr. Mistoffelees.

Some problems specific to the Dual XHD7714:

Bluetooth issues:

  • Bluetooth headset mode only syncs with one phone at a time. This seems to be a common limitation of low-end bluetooth car stereos, but it’s quite frustrating for two-driver families like mine.
  • Bluetooth audio streaming mode doesn’t sound very good on this radio. However, I didn’t experiment with this very much, so it may have been source-material related.

USB MP3 player issues:

  • It takes about 5 seconds per GB to index USB stick music each time it starts up.
  • It only recognizes US-ASCII characters. If any non-ASCII characters are present in the album or song name the entire name is replaced with the string “Not supported”. We had a lot of Chinese-language tracks that displayed that way, making them very difficult to navigate.
  • It can’t fast-forward or rewind through MP3s.
  • When you turn on the radio, it does remember where in the current MP3 it is playing, but it takes a long time to resume playing an MP3 in the middle. So it’s awkward listening to long podcasts.

Still, even with all these flaws, I’m quite happy with the radio. We really enjoyed being able to conveniently listen to so many different songs during our trip.