aboutsummaryrefslogtreecommitdiff
path: root/titlecomp.pl
diff options
context:
space:
mode:
authorB. Watson <yalhcru@gmail.com>2016-01-06 01:55:41 -0500
committerB. Watson <yalhcru@gmail.com>2016-01-06 01:55:41 -0500
commitad615f1eb4febb59f5148ba356d9ad91dc72db09 (patch)
tree1ac19501a81295c9e7df255ef6196c63545cf7fa /titlecomp.pl
parent78955cb3856cfc0115c7e2f2813132cc46c4fd23 (diff)
downloadtaipan-ad615f1eb4febb59f5148ba356d9ad91dc72db09.tar.gz
compressed title image, loads faster
Diffstat (limited to 'titlecomp.pl')
-rw-r--r--titlecomp.pl95
1 files changed, 95 insertions, 0 deletions
diff --git a/titlecomp.pl b/titlecomp.pl
new file mode 100644
index 0000000..2e17a92
--- /dev/null
+++ b/titlecomp.pl
@@ -0,0 +1,95 @@
+#!/usr/bin/perl -w
+
+$datasize = 0x1700;
+
+use bytes;
+
+# skip xex header
+read(STDIN, our $junk, 6);
+
+read(STDIN, $data, $datasize);
+
+for(split //, $data) {
+ $got{ord($_)}++;
+}
+
+$firstcode = shift || 128; # must be >=128
+for($firstcode..255) {
+ push @available_codes, $_ unless $got{$_};
+}
+print scalar keys %got, " unique byte values\n";
+print scalar @available_codes . " available run codes >= $firstcode\n";
+
+sub allocate_code {
+ if(!@available_codes) {
+ die "out of run codes!\n";
+ }
+
+ return shift @available_codes;
+}
+
+# add a $ff to the end, to force the last run to be written
+# if the file ends in a run. Remove it afterwards.
+$run = 0;
+$output = "";
+for(split //, $data . chr(0xff)) {
+ if($_ eq "\0") {
+ if($run) {
+ $run++;
+ } else {
+ $run = 1;
+ }
+ } else {
+ if($run > 1) {
+ if($runlengths{$run}) {
+ $output .= chr($runlengths{$run});
+ } else {
+ my $code = allocate_code();
+ $runlengths{$run} = $code;
+ $used_codes{$code} = $run;
+ $output .= chr($code);
+ $lastcode = $code;
+ }
+ } elsif($run == 1) {
+ $output .= "\0";
+ }
+ $run = 0;
+ $output .= $_;
+ }
+}
+
+# remove the $ff we added above.
+substr($output, -1) = "";
+
+open $out, ">comptitle.dat";
+print $out $output;
+close $out;
+
+$pct = int(length($output) * 1000 / length($data))/ 10;
+print "1st code $firstcode, last $lastcode, table size " . ($lastcode - $firstcode + 1) . "\n";
+print length($output) . " bytes compressed data, $pct% ratio\n";
+print "used " . keys(%runlengths) . " codes\n";
+
+
+for($firstcode..$lastcode) {
+ $table .= " .byte ";
+ if(exists($used_codes{$_})) {
+ $table .= '$' . sprintf("%02x", $used_codes{$_}) . " ; " . sprintf("%02x", $_);
+ } else {
+ $table .= "\$00 ; SELF";
+ }
+ $table .= "\n";
+}
+
+open $in, "<comptitle.s.in" or die $!;
+open $out, ">comptitle.s" or die $!;
+
+while(<$in>) {
+ s/__TABLE__/$table/;
+ s/__FIRSTCODE__/$firstcode/g;
+ s/__LASTCODE__/$lastcode/g;
+ print $out $_;
+}
+
+close $in;
+close $out;