Another night of .obj failure
This commit is contained in:
@@ -19,7 +19,6 @@ module Obj
|
||||
|
||||
def self.parse(data)
|
||||
hdr = new(*data[0..SIZE - 1].unpack("V*"))
|
||||
pp hdr
|
||||
hdr.validate!(data.bytes.size)
|
||||
hdr
|
||||
end
|
||||
@@ -82,8 +81,6 @@ module Obj
|
||||
DirEntry.parse(rel_data.byteslice(rel_offset, DirEntry::SIZE))
|
||||
end
|
||||
|
||||
pp entries
|
||||
|
||||
new(entries)
|
||||
end
|
||||
|
||||
@@ -94,38 +91,58 @@ module Obj
|
||||
# Convert the directory into an Array of bytes. Until we work out how to
|
||||
# parse sprites, anyway...
|
||||
def realize(rel_data)
|
||||
entries.map { |entry| rel_data[entry.sprite_range] }
|
||||
entries.map { |entry| Sprite.parse(rel_data[entry.sprite_range]) }
|
||||
end
|
||||
end
|
||||
|
||||
=begin
|
||||
SpriteHeader = Struct.new(
|
||||
:unknown0, # Possibly magic data? It's the same for every sprite in jungtil.obj
|
||||
:maybe_dimension, # Low nibble comes to 63 in jungtil.obj which would work for a 64x64 tile
|
||||
:size, # Number of bytes of pixel data following this header
|
||||
) do
|
||||
SIZE = 4*6 # Seems to be, anyway. Based on
|
||||
class SpriteHeader
|
||||
SIZE = 24 # Seems to be, anyway. Based on the size here vs. the size in the dir
|
||||
|
||||
attr_reader(
|
||||
:unknown0, # Possibly magic data? It's the same for every sprite in jungtil.obj
|
||||
:width, # Low nibble comes to 63 in jungtil.obj which would work for a 64x64 tile
|
||||
:height,
|
||||
:unknown8,
|
||||
:size, # Number of bytes of pixel data following this header
|
||||
:unknown16,
|
||||
:unknown20,
|
||||
)
|
||||
|
||||
def self.parse(rel_data)
|
||||
new(*sprite_data[0..SIZE-1]).unpack("V*")
|
||||
new(*rel_data[0...SIZE].unpack("VvvVVVV"))
|
||||
end
|
||||
|
||||
def initialize(*args)
|
||||
@unknown0,
|
||||
@width,
|
||||
@height,
|
||||
@unknown8,
|
||||
@size,
|
||||
@unknown16,
|
||||
@unknown20 = *args
|
||||
end
|
||||
|
||||
def pixel_range
|
||||
SIZE...size # maybe,anyway
|
||||
SIZE...(SIZE+size)
|
||||
end
|
||||
end
|
||||
|
||||
Sprite = Struct.new(
|
||||
:header, :data
|
||||
) do
|
||||
class Sprite
|
||||
attr_reader :header, :data, :raw
|
||||
|
||||
def self.parse(rel_data)
|
||||
hdr = SpriteHeader.parse(rel_data)
|
||||
sprite_pixels = rel_data[hdr.pixel_range]
|
||||
|
||||
Sprite.new(hdr, sprite_pixels)
|
||||
new(hdr, sprite_pixels, rel_data)
|
||||
end
|
||||
|
||||
def initialize(header, data, raw = nil)
|
||||
@header = header
|
||||
@data = data
|
||||
@raw = raw
|
||||
end
|
||||
end
|
||||
=end
|
||||
|
||||
class Parsed
|
||||
attr_reader :header
|
||||
@@ -210,10 +227,11 @@ end
|
||||
|
||||
def dump(filename, spriteno = -1)
|
||||
obj = load_obj(filename)
|
||||
# pp obj
|
||||
|
||||
if spriteno == -1
|
||||
puts "Dumping all sprites for #{filename}"
|
||||
obj.sprites.each { |sprite| display(sprite, header: true) }
|
||||
obj.sprites.each { |sprite| display(sprite.raw, 2, header: true) }
|
||||
else
|
||||
puts "Dumping sprite #{spriteno} for #{filename}"
|
||||
display(obj.sprites[spriteno])
|
||||
@@ -227,37 +245,61 @@ end
|
||||
# * DEFLATE / ZLIB
|
||||
# * LZO
|
||||
# * LZOP
|
||||
# * RLE (maybe?)
|
||||
#
|
||||
# Maybe try:
|
||||
# * RLE8: https://www.fileformat.info/format/bmp/corion-rle8.htm
|
||||
|
||||
def decompress(filename)
|
||||
puts "\nAttempting decompression of #{filename}..."
|
||||
|
||||
require 'zlib'
|
||||
puts "\nAttempting RLE decompression of #{filename}..."
|
||||
|
||||
obj = load_obj(filename)
|
||||
|
||||
obj.sprites.each_with_index do |sprite, 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|
|
||||
block = sprite.byteslice(offset, sprite.size-offset)
|
||||
decompressed = []
|
||||
data = sprite.data.bytes
|
||||
hdr = sprite.header
|
||||
|
||||
begin
|
||||
inflater = Zlib::Inflate.new(-32)
|
||||
decompressed = ""
|
||||
decompressed << inflater.inflate(block)
|
||||
raise "0 bytes" if decompressed.size == 0
|
||||
(0...hdr.height).each do |i|
|
||||
# npackets = data.shift(1)[0] # ignore the packet byte
|
||||
decompressed_line = []
|
||||
|
||||
puts "succeeded! sprite=#{i} offset=#{offset} decompressed_size=#{decompressed.size}"
|
||||
puts "data:"
|
||||
puts decompressed.inspect
|
||||
exit 0
|
||||
rescue => err
|
||||
puts "failed: #{err}"
|
||||
count = 0
|
||||
loop do
|
||||
cmd = data.shift(1)[0]
|
||||
if cmd == 0 # end of stream
|
||||
print "Done! #{data.size} bytes left. "
|
||||
break
|
||||
elsif cmd == nil
|
||||
print "Ran out of data! "
|
||||
break
|
||||
elsif cmd > 128 # "negative" bytes say "copy abs(X) bytes unmodified from input to output"
|
||||
decompressed_line.concat(data.shift(cmd-128))
|
||||
else # "positive" bytes say "repeat the next byte X times"
|
||||
decompressed_line.concat(data.shift(1)*cmd)
|
||||
end
|
||||
|
||||
if decompressed_line.size == hdr.width
|
||||
print "Done line! "
|
||||
break
|
||||
end
|
||||
|
||||
# if npackets > 0 && count == npackets
|
||||
# print "Done packets! "
|
||||
# break
|
||||
# end
|
||||
|
||||
count+=1
|
||||
end
|
||||
|
||||
raise "Bad length for line #{i}! #{decompressed_line.size} (Expected #{hdr.width})" if decompressed_line.size != hdr.width
|
||||
decompressed << decompressed_line
|
||||
end
|
||||
|
||||
#puts "failed"
|
||||
puts "Decompressed: #{decompressed.flatten.size} bytes. Sprite pixels: #{hdr.width*hdr.height}"
|
||||
#display(decompressed.map(&:chr).join(""))
|
||||
end
|
||||
end
|
||||
|
||||
@@ -277,7 +319,29 @@ def compare(filenames)
|
||||
end
|
||||
end
|
||||
|
||||
def sprites(filename)
|
||||
obj = load_obj(filename)
|
||||
|
||||
puts filename + ":"
|
||||
puts "\ti X Y Px bytes bits/px"
|
||||
obj.sprites.each_with_index do |spr, i|
|
||||
hdr = spr.header
|
||||
px = hdr.width * hdr.height
|
||||
|
||||
puts "\t%02d: %03d %03d %04d %04d %.2f"%[
|
||||
i,
|
||||
hdr.width,
|
||||
hdr.height,
|
||||
px,
|
||||
hdr.size,
|
||||
(hdr.size*8) / px.to_f
|
||||
]
|
||||
end
|
||||
end
|
||||
|
||||
case command = ARGV.shift
|
||||
when "sprites" then
|
||||
ARGV.each { |filename| sprites(filename) }
|
||||
when "dump" then
|
||||
ARGV.each { |filename| dump(filename) }
|
||||
when "compare" then
|
||||
|
Reference in New Issue
Block a user