Turns out the palette is actually identical to that in wh40k.pcx

This commit is contained in:
2018-03-25 00:18:27 +00:00
parent 285ae5d292
commit c8238f1853
12 changed files with 959 additions and 13 deletions

View File

@@ -18,7 +18,7 @@ module Obj
)
def self.parse(data)
hdr = new(*data[0..SIZE - 1].unpack("V*"))
hdr = new(*data[0..SIZE - 1].unpack("VVVVV"))
pp hdr
hdr.validate!(data.bytes.size)
hdr
@@ -28,6 +28,16 @@ module Obj
@num_sprites, @dir_offset, @dir_size, @data_offset, @data_size = *entries
end
def to_data
[
@num_sprites,
@dir_offset,
@dir_size,
@data_offset,
@data_size,
].pack("VVVVV")
end
def validate!(overall_size)
raise "Directory overlaps EOF" if overall_size < dir_size + dir_offset
raise "Data overlaps EOF" if overall_size < data_offset + data_size
@@ -62,6 +72,10 @@ module Obj
@sprite_size = sprite_size
end
def to_data
[rel_offset, sprite_size].pack("VV")
end
def sprite_range
rel_offset...(rel_offset+sprite_size)
end
@@ -91,8 +105,11 @@ module Obj
@entries = entries
end
# Convert the directory into an Array of bytes. Until we work out how to
# parse sprites, anyway...
def to_data
entries.map(&:to_data).join("")
end
# Convert the directory into an Array of sprites
def realize(rel_data)
entries.map { |entry| Sprite.parse(rel_data[entry.sprite_range]) }
end
@@ -125,6 +142,18 @@ module Obj
@unknown20 = *args
end
def to_data
[
@unknown0,
@width,
@height,
@unknown8,
@size,
@unknown16,
@unknown20
].pack("VvvVVVV")
end
def pixel_range
SIZE...(SIZE+size)
end
@@ -148,6 +177,15 @@ module Obj
@records = records
@raw = raw
end
# raw is optional, so don't use it here
def to_data
header.to_data + records.join("")
end
def total_size
SpriteHeader::SIZE + records.join("").size
end
end
class Parsed
@@ -161,6 +199,19 @@ module Obj
@directory = directory
@sprites = sprites
end
def to_data
dir_padding = "\x00"*(header.dir_offset - Header::SIZE)
data_padding = "" # for now, assume all is well
[
header.to_data,
dir_padding,
directory.to_data,
data_padding,
sprites.map { |sprite| sprite.to_data },
].join("")
end
end
def self.parse(data)
@@ -383,6 +434,70 @@ def sprite(filename, i)
end
end
# Build a test sprite to investigate the color palette
def build(filename)
sprite_records = [
# 63 in each sprite except the last, which has just 3
1.upto(63).map { |b| "\x01#{b.chr}\x00" },
64.upto(126).map { |b| "\x01#{b.chr}\x00" },
127.upto(189).map { |b| "\x01#{b.chr}\x00" },
190.upto(252).map { |b| "\x01#{b.chr}\x00" },
253.upto(255).map { |b| "\x01#{b.chr}\x00" },
]
sprites = sprite_records.map do |records|
data = records.join("")
header = Obj::SpriteHeader.new(
0, # Stolen from blank.obj
1, # width of 1
records.size, # height = number of records
0, # padding?
data.size,
0, # padding?
0, # padding?
)
Obj::Sprite.new(
header,
records,
header.to_data + data,
)
end
dir_block_offset = 32 # hardcoded
dir_block_size = 8 *sprites.size
data_block_offset = dir_block_offset + dir_block_size
data_block_size = sprites.inject(0) { |x, spr| x + spr.total_size }
header = Obj::Header.new(
sprites.size,
dir_block_offset,
dir_block_size,
data_block_offset,
data_block_size,
)
offset = 0
directory = Obj::SpriteDir.new(
sprites.map { |sprite|
puts "offset #{offset} => #{sprite.total_size}"
entry = Obj::DirEntry.new(offset, sprite.total_size)
offset += sprite.total_size
entry
}
)
pp directory
built = Obj::Parsed.new(
header,
directory,
sprites
)
File.open(filename, "w") { |f| f.write(built.to_data) }
end
case command = ARGV.shift
when "sprites" then
ARGV.each { |filename| sprites(filename) }
@@ -396,6 +511,8 @@ when "decompress" then
ARGV.each { |filename| decompress(filename) }
when "correlate" then
correlate(ARGV)
when "build" then
build(ARGV[0])
else
puts "Unrecognized command #{command}"
exit(1)