Friday, March 21, 2008

WTF - Changing keymaps with a hex editor

Maine coon kittens by eleda from flickr (CC-NC)

I had a sudden attack of nostalgia today so I grabbed a few random Nintendo ROMs and tried to play them. Surprisingly while hardware SNES had no problem with NES games, SNES emulators don't like NES ROMs claiming they're corrupt. I think they should at least say something like "This looks like a NES ROM not SNES ROM, please use another program" but that's a subject for another rant.

I got FCE Ultra which is a proper NES emulator. The only problem was completely absurd keymapping, AWZS being arrows, and keypad 2/3 being buttons. It was completely unusable on either laptop keyboard or external keyboard and it wasn't customizable. I tried one more emulator (nestra) but there was no sound so I had to go back to FCE Ultra. Not a big deal I thought - I have sources, so apt-get source fceu; sudo apt-get build-dep fceu and let's see how the input is handled. I found data structure defining keymaps in no time, changed it to cursors+ZX, recompiled and ... it still used the old keymap.

No need to panic I thought, maybe there's another keymap somewhere. There wasn't. So maybe make dependencies are broken and I need to make clean first... still didn't work. I even started suspecting that libtool or some other part of the build system might store old object files somewhere. No worries here, let's just get fresh sources, patch input.c, recompile and ... back to the old keymap.

Now that was weird. There was definitely no other keymap, debug printfs in input.c worked, and all the functions I expected were called. A few more printfs - keymap data structure contained 97, 119, 122, 115 (awzs) instead of arrow keycodes. That was a major WTF. Obviously something must have modified the keymap, but how did it know the old one?

The solution wasn't that far away - FCE Ultra concatenates all configuration data structures (keymaps, sound settings, palletes, GUI config and everything else) into one huge structure which is saved to disk and then reloaded overwriting program's manually defined data structures. It's not even serialized in any way, it's pure binary data the way compiler arranges it. Only a C programmer might have done something like that. People who program in literally anything else - even Java - would either do text/XML serialization or wouldn't bother at all. What was the thinking process of the guy who wrote that code? My best guess is "Maybe someone will want to change keymaps with a hex editor".

Sunday, March 02, 2008

Practical Ruby Projects review

Foto Kotki by RussianA from Wikimedia Commons (CC-BY)

A few weeks ago I got a review copy of "Practical Ruby Projects: Ideas for the Eclectic Programmers" by Topher Cyll. The main part of the book consists of eight thematic chapters: MIDI music, SVG animation, pocket change problem, turn-based strategy engine, turn-based strategy GUI in Cocoa, genetic algorithms, implementing Lisp in Ruby (what probably got me the review copy), and parsing with RParsec. But don't worry about that, they are only pretexts for demonstrating various genuine issues that you will stumble upon in your Ruby coding and various interesting techniques. In a way the book reads a lot like a typical programming blog, with all the "I had this strange problem while coding something, and I solved it in this incredibly cool way, I hope it's useful to you too" stuff.

The book is very high on code and pretty low on bullshit and beginner filler (which unfortunately plagues so many books these days), so it won't be wasting your time. I was surprised by how many solutions presented in the book were almost identical to what I've done in my projects, like world map implementation in the book's Cocoa app and my jrpg, which uses Python and PyGame/SDL but is surprisingly similar in structure. The part that was most interesting to me was the last chapter with RParsec tutorial, but the book was overall very enjoyable to read.

If you want me to review any other good books, go ahead and send them ;-)