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".

3 comments:

  1. Anonymous03:24

    fceu -inputcfg gamepad1 /dev/null provides an interface for remapping controls. Not very obvious, but there it is.

    ReplyDelete
  2. greetings from Wroclaw / Chojnow :) I hope You have rest a bit without programming this Easter :D

    pozdrówka!! :)

    ReplyDelete
  3. Anonymous23:39

    Hah - I thought you'd pass your First Certificate with FCE Ultra ;P
    Greetings from Earth... Greetings from Wiki.

    ReplyDelete