Hacking ReplayTV

A few weeks ago someone contacted me regarding my OMFS filesystem driver for the Rio Karma. His interest is in getting it working for ReplayTV to do who knows what. This is coming a bit full circle, as I discovered long ago that the RK and RTV use the same proprietary filesystem, and indeed the ReplayTV hackers of yore had documented nearly everything there is to know about the FS, without which I would’ve been lost writing the Linux kernel driver in the first place. Of course, there are some differences in the way the two devices do their thing.

I don’t own an RTV, but I like a challenge so I asked him to send me a dump of the first gig of the disk. One look and it is the crack-headedest thing I’ve seen in some time: somewhere along the way, their block layer must’ve moved from a big-endian to little-endian platform, without changing the code. OMFS is a 64-bit FS but the RTV block layer apparently works on 32 bits, so for example the 64-bit value 0x8877665544332211 gets written to disk as 0x5566778811223344. And it’s not just the metadata: *everything* is swapped. Filenames look like “tusCzimo..re” instead of “Customizer”. File data blocks are all swapped. Very odd.

Well, for a time I’ve been wanting to experiment with OMFS written in FUSE, so I took my userspace routines from omfsprogs and in the space of an hour or two had a read-only FUSE-based OMFS that did the necessary byte swapping to work with Replay’s file system.

The payoff is the text file that RTV developers apparently used in their version control process. I give you: ReplayTV “Token Haiku” (after the jump).
Continue reading “Hacking ReplayTV”

I dislike Java.

Dear lazy web,

It would be nice if you could tell me a non-hacky way to do progress dialogs from within the event-dispatch thread in Swing, where all of our application logic happens to reside.

This doesn’t work:
display modal dialog
start worker thread
(won’t run because event thread is blocked)

Nor does this:
start worker thread
display modal dialog
(race condition hiding the dialog)

Joining in the event thread won’t work because it blocks updates. Using a non-modal dialog and passing the bottom-half of the rest of the event thread to the worker thread to execute at completion will work, but is obscenely messy. Or, one can spin in the beginning of the thread waiting for the modal dialog to appear to avoid the race condition, but that is still gross. One could subclass Dialog and have it also signal a condition variable once it blocks… ugh.

Hello, java!

I was messing around with Java bytecode today for no particular reason. It’s a fairly simple assembly language — stack based so it takes a little getting used to but not hard for anyone who has used an HP calculator. I installed a copy of jasmin from my apt repository and got to work.

I wanted to make a “Hello, world!” that wasn’t completely obvious at first blush, so the plan of attack was to just push all the ascii codes on the stack in reverse order then call System.out.print() on them in a loop. Each iteration checks the loop count, if ok then pop the next code and print it. Here is where the bytecode verifier is a pain in the ass: apparently, the instructions must be executed each time through a loop with the same stacksize, or else you are branded an evil hacker. Very annoying. I could’ve used an array instead but that also takes a bunch of pushes and stores, so I just unrolled the loop. It works, I guess. Code after the jump.
Continue reading “Hello, java!”

blocks

It can be a humbling experience to revist old code. And I’m not talking about the dynamic simulation stuff, which is obviously a hack on top of a pile of hacks. No, this week I returned to my old pal ansiconv, the program that converts text files to images of the text file, rendering it as if you had ANSI.SYS loaded and typed TYPE KOOL.ANS at the cee colon backslash prompt. This program had achieved a modicum of success in its heyday but lately various alternatives have popped up written in languages such as C# and PHP. Being the C bigot that I am (one who writes Java for a living), I thought I would update this one great program, slap a PHP module interface on it, and unleash it upon the world.

Stylistically, the program was a mess: 2-space indentations, curly braces on the same line as the function definition, spaces (( after the )) parentheses, seemingly no rhyme or reason to naming of typedefs, and, horror of horrors, extensive use of studlyCaps. Oh, how I had strayed from the Unix flock. Even worse, I found an obvious bug in TAB character handling; a memleak or two in the error paths; infrequent to non-existent use of the static keyword; global variables aplenty, in one place documented “to ease calling into functions” (had I some phobia of struct?); and even a case of a function returning a pointer to a global variable. Take that ctime(3). All this in the space of some 2 KLOC.

The good news is, a few hours with vim and the codebase is much better: no more globals, no more leaks, no more uglyNamingConventions. I changed the build to create a library with a single entry point, which the ansiconv binary uses to work its magic. All the CGI support code was ripped out, and I wrote a small PHP module that utilizes libansiconv to do stuff on the web. Finally, I borrowed an enhancement from our friends who wrote the newer ansi converters, which is to emit 4 bits-per-pixel images when we can to reduce their size.

The other ansi converters are more full-featured, but C still wins in speed, hands down. A rough test shows ansiconv converts around 2500 ansis/minute, compared with 270 ansis/min for another popular PHP converter (both tests include the overhead of starting the PHP interpreter).

If you have no freakin clue what this post is on about, visit Doug’s great page, 16c.

Open sores

Well, as of yesterday, after a long protracted review and release process, several lines of code by me have found their way into an operating system: Linux 2.6.16 includes my Rio Karma drivers. So you can go ahead and blame me if Linux sucks. Then I’ll blame Jeff Garzik in turn, just because.

Last weekend was nice. Angeline and I spent most of it shopping for her DC area apartment for her new job at NIH beginning this summer. If anyone knows of a cheap but nice apartment convenient to Bethesda, let’s hear it.

Note to job seekers: don’t put “career” or “job” in your resume. I keep getting keyword searches in my httpd logs for “objective education experience oracle unix -job -career.” I guess said headhunters won’t see this post, so let me take this opportunity to tell them that they are ugly and they smell. I also get lots of referrer spam from ballsacks.net. Just thought you should know.

jconsole

I still hate Java, but I do have to say that J2SE “5” is a much needed improvement. Ahh, generics, where have you been all this time? This week I’ve been rewriting an old buggy, crufty server we had sitting around (before: 5000 lines of code, after: 600) and discovered one of the neatest new whizbang features: jconsole, a standalone JVM monitor and JMX console. If you’ve used JBoss’ jmx-console webapp before, it’s the same idea, just prettier.

All you have to do to use it is add -Dcom.sun.management.jmxremote to the java command line, and then run jconsole. Then you can monitor memory usage, get live stack traces on all the running threads, and get general VM statistics. If you create an MBean interface and implementation and register it with the platform MBean server, then you can interact with the application just as if deployed in a JMX container. For example, I have MBean methods to make the server enter and leave maintenance mode for software upgrades. To use them, we just connect with jconsole and click the proper button. Neat.

in-kernel

ChangeLog-2.6.16-rc1:

commit 0e6e1db4ac7acfe3e38bbef9eba59233ba7f6b9a
Author: Bob Copeland 
Date:   Mon Jan 16 22:14:20 2006 -0800

[PATCH] partitions: Read Rio Karma partition table

The Rio Karma portable MP3 player has its own proprietary partition table.

The partition layout is similar to a DOS boot sector but it begins at a
different offset and uses a different magic number (0xAB56 instead of
0xAA55).  Add support for it to enable mounting the device.

Signed-off-by: Bob Copeland 
Signed-off-by: Andrew Morton 
Signed-off-by: Linus Torvalds 

Who wants to touch me?

Nerd stuff

I’m entering a new phase in the product cycle at work so I get to think more about the current state of the way-behind-the-times while designing a new system.

Swing’s MVC design for tables and combo boxes and so on totally misses the point. MVC is about abstracting away the UI from the model; making the tables explicitly require a model that implements a javax.swing interface does nothing to reduce the coupling between interface and core code. What if I want a curses-based view instead of Swing on top of the same model? I am annoyed that Gtk2 seems to have picked up this misfeature.

Why did Java “5” introduce only an “enhanced for-loop” to go with generics? They should’ve taken a cue from STL and stressed algorithmic reuse. Where is a method like Perl’s map? Also, while we’re at it, I want real closures.

EJB is way too complex, and Sun figured that out, and released a new spec. So far things are looking much better. I don’t like annotations as they clutter the code and seem like a reinvention of #pragma: it looks like something the compiler shouldn’t know about, but does. On the other hand deployment descriptors were 1e15 times worse. The EJB 3 persistence model is a lot cleaner, and surprise, you can use your database code outside the container now. Way to finally support one of the basic goals of OO. In fact, I had a real-world problem to solve earlier this year: write a small application that reuses our DB backend stuff, all command line based, without hitting the EJB tier. This is harder than it sounds, and eventually had me writing my own datasource provider with connection and statement pooling that wrapped the JDBC drivers of our database. Ick.

I hate VMs. Operating systems are there for a reason. If I get another OutOfMemory exception because I didn’t pass -Xmx19201231230 to my leak-free Java program…

AJAX? A new name for what we did with javascript in hidden frames back in 1996? Okay, XmlHttpRequest, I’ll give you that. But it doesn’t deserve being thought of as a new technology. Same for “Service Oriented Architecture,” “Enterprise Service Bus,” and every other re-invention of RPC.

I still think Grady Booch is an idiot.

Kernel programming is fun: you can use goto, bitwise ops, cast pointers to structures, and it’s all okay. Also: don’t comment too much.

hashed

Despite earning my degree in computer engineering, I haven’t done anything useful with assembly language since I was a strapping young idealistic lad convinced that compilers lie along the road to inefficiency. Much has changed. Heck, I write Java code for a living now — pretty much the opposite of efficient. I have to have a gig of ram just to run that sucky ant program.

While hacking my MP3 player, I discovered that the filesystem uses hashing to quickly lookup file names, which brought up the question of which hash function it uses. While I suppose one could reverse the hash function knowing a very large set of inputs and outputs, I decided it would probably be much more expedient to just put my atrophied x86 asm knowledge to work for me.

This turned out to be a lot easier than I thought. It only took about 20 minutes and I never had to step through code in a debugger.

Step 1: Disassemble Windows program for loading files onto the device, including the data segment. Look for the offset of a useful printf format string (“hash is %d, expected %d”).
Step 2: Search disassembly for loading said offset in a call to printf. Not surprisingly, this is right after the computation of the hash.
Step 3: Examine nearby calls for things like shifts and mods (common hashing operations).
Step 4: Relearn the stupidities of the x86 ISA (ecx is a loop counter, eax and edx figure in mysteriously for divides, etc).
Step 5: Convinced that a nearby call is it, reimplement in C and test.

Booyeah.