Skip to content

Instantly share code, notes, and snippets.

@bortels
Created December 2, 2011 07:57
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save bortels/1422256 to your computer and use it in GitHub Desktop.
Save bortels/1422256 to your computer and use it in GitHub Desktop.
Decode a .codea rtfd file
#!/usr/bin/perl
# Tom's nasty and ugly .codea (rtfd) decoder
# I release this bad boy to the public domain, you can't stop me!
$debug=1;
$f = shift @ARGV || "Font.codea";
open ($fh, $f);
my $c = do { local $/; <$fh> }; # slurp
close $fh;
$header = unpack("A4", $c); $c = substr($c, 4);
if ($header ne "rtfd") { die "The file $f is not a Codea archive\n"; }
$buffer = unpack("N", $c); $c = substr($c, 4);
$version = unpack("l", $c); $c = substr($c, 4); # just guessing!
$files = unpack("l", $c); $c = substr($c, 4);
if ($debug) { print "$files files:\n"; }
for $f (1..$files) {
$namelen = unpack("l", $c); $c = substr($c, 4);
$name = unpack("A$namelen", $c); $c = substr($c, $namelen);
if ($debug) { print "$f: $name\n"; }
$NAME{$f} = $name;
}
for $f (1..$files) {
$size = unpack("l", $c); $c = substr($c, 4);
if ($debug) { print "$f: $NAME{$f} chunk is $size\n"; }
$SIZE{$f} = $size;
}
$thisfile = 0;
while ($thisfile < $files) { # now process each chunk
$thisfile++;
$quiet = 0; # skip garbage files
if ($NAME{$thisfile} eq '.') { $quiet++; }
if ($NAME{$thisfile} =~ /@/) { $quiet++; }
$s = $SIZE{$thisfile};
if (! $quiet) { print "file $thisfile $NAME{$thisfile} - "; }
$fc = unpack("A$s", $c); $c = substr($c, $s);
$x = unpack("l", $fc); $fc = substr($fc, 4); # junk
$x = unpack("l", $fc); $fc = substr($fc, 4); # size, or
if ($x == -2147483648) { # Why??? minval
$x = unpack("l", $fc); $fc = substr($fc, 4); # then size. Weird.
}
if (! $quiet) {
print "$x bytes\n" . substr($fc, -$x);
print "\n---------------------------------------------------------\n\n";
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment