Partially implemented improvements to scripts/try-uncompress
This commit is contained in:
@@ -1,6 +1,7 @@
|
|||||||
#!/usr/bin/env ruby
|
#!/usr/bin/env ruby
|
||||||
|
|
||||||
require 'pp'
|
require 'pp'
|
||||||
|
require 'digest/md5'
|
||||||
|
|
||||||
module Obj
|
module Obj
|
||||||
class Header
|
class Header
|
||||||
@@ -130,6 +131,7 @@ module Obj
|
|||||||
attr_reader :header
|
attr_reader :header
|
||||||
attr_reader :directory
|
attr_reader :directory
|
||||||
attr_reader :sprites
|
attr_reader :sprites
|
||||||
|
attr_accessor :filename
|
||||||
|
|
||||||
def initialize(header, directory, sprites)
|
def initialize(header, directory, sprites)
|
||||||
@header = header
|
@header = header
|
||||||
@@ -147,48 +149,96 @@ module Obj
|
|||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
parsed = Obj.parse(File.read("orig/Obj/jungtil.obj").force_encoding("BINARY"))
|
|
||||||
|
|
||||||
def hex(num, leading=0)
|
def hex(num, leading=0)
|
||||||
|
return " "*(leading) if num.nil?
|
||||||
|
|
||||||
"%0#{leading}x"%num
|
"%0#{leading}x"%num
|
||||||
end
|
end
|
||||||
|
|
||||||
def display(data, blocksize=8, skip=0)
|
VISIBLE_CHARS = ("0".ord)..("z".ord)
|
||||||
bytes = data.bytes
|
def text(num)
|
||||||
|
return " " if num.nil?
|
||||||
|
if VISIBLE_CHARS.cover?(num)
|
||||||
|
num.chr
|
||||||
|
else
|
||||||
|
" "
|
||||||
|
end
|
||||||
|
end
|
||||||
|
|
||||||
|
def ascii(num)
|
||||||
|
return " " if num.nil?
|
||||||
|
|
||||||
|
"%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)
|
nrows = (bytes.count / blocksize)
|
||||||
|
|
||||||
skip.upto(nrows) do |i|
|
0.upto(nrows) do |i|
|
||||||
|
header!(blocksize) if i%16==0 || i == skip
|
||||||
block = bytes[(i*blocksize)...(i*blocksize+blocksize)]
|
block = bytes[(i*blocksize)...(i*blocksize+blocksize)]
|
||||||
|
|
||||||
|
block.concat([nil]*(blocksize-block.size)) if block.size < blocksize
|
||||||
|
|
||||||
out = [
|
out = [
|
||||||
"0x#{hex(i*blocksize, 4)}",
|
"0x#{hex(i*blocksize, 4)}",
|
||||||
block.map { |b| hex(b, 2) },
|
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 out.flatten.join(' ')
|
||||||
|
# puts Digest::MD5.hexdigest(data[skip..-1])
|
||||||
end
|
end
|
||||||
end
|
end
|
||||||
|
|
||||||
|
def load_obj(filename)
|
||||||
|
Obj.parse(File.read(filename).force_encoding("BINARY"))
|
||||||
|
end
|
||||||
|
|
||||||
puts "Dumping blank sprite"
|
def dump(filename, spriteno = -1)
|
||||||
display(parsed.sprites[0], 8, 0)
|
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,
|
# 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.
|
# 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:
|
# Tried so far, with no success:
|
||||||
# * DEFLATE / ZLIB
|
# * DEFLATE / ZLIB
|
||||||
# * LZO
|
# * LZO
|
||||||
# * LZOP
|
# * LZOP
|
||||||
|
|
||||||
|
def decompress(filename)
|
||||||
puts "\nAttempting decompression..."
|
puts "\nAttempting decompression of #{filename}..."
|
||||||
|
|
||||||
require 'zlib'
|
require 'zlib'
|
||||||
|
|
||||||
parsed.sprites.each_with_index do |sprite, i|
|
obj = load_obj(filename)
|
||||||
|
|
||||||
|
obj.sprites.each_with_index do |sprite, i|
|
||||||
print "Sprite %02d..."%i
|
print "Sprite %02d..."%i
|
||||||
|
|
||||||
|
# Step through the start of each sprite so we aren't stopped by a hypothetical header
|
||||||
(0...64).each do |offset|
|
(0...64).each do |offset|
|
||||||
block = sprite.byteslice(offset, sprite.size-offset)
|
block = sprite.byteslice(offset, sprite.size-offset)
|
||||||
|
|
||||||
@@ -209,4 +259,32 @@ parsed.sprites.each_with_index do |sprite, i|
|
|||||||
|
|
||||||
#puts "failed"
|
#puts "failed"
|
||||||
end
|
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
|
||||||
|
Reference in New Issue
Block a user