diff --git a/scripts/try-uncompress b/scripts/try-uncompress index 1cd8f5e..f82dd3f 100755 --- a/scripts/try-uncompress +++ b/scripts/try-uncompress @@ -1,6 +1,7 @@ #!/usr/bin/env ruby require 'pp' +require 'digest/md5' module Obj class Header @@ -130,6 +131,7 @@ module Obj attr_reader :header attr_reader :directory attr_reader :sprites + attr_accessor :filename def initialize(header, directory, sprites) @header = header @@ -147,66 +149,142 @@ module Obj end end -parsed = Obj.parse(File.read("orig/Obj/jungtil.obj").force_encoding("BINARY")) - def hex(num, leading=0) + return " "*(leading) if num.nil? + "%0#{leading}x"%num end -def display(data, blocksize=8, skip=0) - bytes = data.bytes - nrows = (bytes.count / blocksize) - - skip.upto(nrows) do |i| - block = bytes[(i*blocksize)...(i*blocksize+blocksize)] - out = [ - "0x#{hex(i*blocksize, 4)}", - block.map { |b| hex(b, 2) }, - ] - - puts out.flatten.join(' ') +VISIBLE_CHARS = ("0".ord)..("z".ord) +def text(num) + return " " if num.nil? + if VISIBLE_CHARS.cover?(num) + num.chr + else + " " end end +def ascii(num) + return " " if num.nil? -puts "Dumping blank sprite" -display(parsed.sprites[0], 8, 0) + "%3d"%num +end + +def header!(blocksize=8) + nums = (0...blocksize).to_a + hdr = " #{nums.join(" ")} #{nums.join("")}" + + puts "-" * (hdr.size + 1) + puts hdr + puts "-" * (hdr.size + 1) +end + +def display(data, blocksize=8, skip=0, header: false) + bytes = data.bytes[skip..-1] + nrows = (bytes.count / blocksize) + + 0.upto(nrows) do |i| + header!(blocksize) if i%16==0 || i == skip + block = bytes[(i*blocksize)...(i*blocksize+blocksize)] + + block.concat([nil]*(blocksize-block.size)) if block.size < blocksize + + out = [ + "0x#{hex(i*blocksize, 4)}", + block.map { |b| hex(b, 2) }, # hex + " | " + block.map { |b| text(b) }.join("") + " |", # ascii + block.map { |b| ascii(b) } ,# decimal bytes + "",# decimal 2-bytes + # decimal 4-bytes + ] + + puts out.flatten.join(' ') + # puts Digest::MD5.hexdigest(data[skip..-1]) + end +end + +def load_obj(filename) + Obj.parse(File.read(filename).force_encoding("BINARY")) +end + +def dump(filename, spriteno = -1) + obj = load_obj(filename) + + if spriteno == -1 + puts "Dumping all sprites for #{filename}" + obj.sprites.each { |sprite| display(sprite, header: true) } + else + puts "Dumping sprite #{spriteno} for #{filename}" + display(obj.sprites[spriteno]) + end +end # The per-sprite data in jungtil.obj is too small to represent a 64x64 block, # even at 1bpp, so try some decompression algorithms to see what comes out. -# Step through every byte of each sprite so we manage if some header is present # # Tried so far, with no success: # * DEFLATE / ZLIB # * LZO # * LZOP +def decompress(filename) + puts "\nAttempting decompression of #{filename}..." -puts "\nAttempting decompression..." + require 'zlib' -require 'zlib' + obj = load_obj(filename) -parsed.sprites.each_with_index do |sprite, i| - print "Sprite %02d..."%i + obj.sprites.each_with_index do |sprite, i| + print "Sprite %02d..."%i - (0...64).each do |offset| - block = sprite.byteslice(offset, sprite.size-offset) + # Step through the start of each sprite so we aren't stopped by a hypothetical header + (0...64).each do |offset| + block = sprite.byteslice(offset, sprite.size-offset) - begin - inflater = Zlib::Inflate.new(-32) - decompressed = "" - decompressed << inflater.inflate(block) - raise "0 bytes" if decompressed.size == 0 + begin + inflater = Zlib::Inflate.new(-32) + decompressed = "" + decompressed << inflater.inflate(block) + raise "0 bytes" if decompressed.size == 0 - puts "succeeded! sprite=#{i} offset=#{offset} decompressed_size=#{decompressed.size}" - puts "data:" - puts decompressed.inspect - exit 0 - rescue => err - puts "failed: #{err}" + puts "succeeded! sprite=#{i} offset=#{offset} decompressed_size=#{decompressed.size}" + puts "data:" + puts decompressed.inspect + exit 0 + rescue => err + puts "failed: #{err}" + end end - end - #puts "failed" + #puts "failed" + end end +# Print the first 128 bytes of sprites in a friendly format. Permits into-obj comparisons +def compare(filenames) + objs = filenames.map { |filename| load_obj(filename).tap { |obj| obj.filename = filename } } + + objs.each do |obj| + + end + + sprites = + if spriteno == -1 + else + + + end +end + +case command = ARGV.shift +when "dump" then + ARGV.each { |filename| dump(filename) } +when "compare" then + compare(filenames) +when "decompress" then + ARGV.each { |filename| decompress(filename) } +else + puts "Unrecognized command #{command}" + exit(1) +end