Partially implemented improvements to scripts/try-uncompress

This commit is contained in:
2018-03-20 02:21:29 +00:00
parent 9b4e2b43e0
commit fad7dec6ab

View File

@@ -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