From 1ea123a20119c8211f0c480a4107c65d879afd19 Mon Sep 17 00:00:00 2001 From: Nick Thomas Date: Wed, 21 Mar 2018 21:26:07 +0000 Subject: [PATCH] More .obj investigation. Looking for records in sprite data --- doc/formats/obj.md | 24 ++++++++---- scripts/try-uncompress | 86 +++++++++++++++++++++++------------------- 2 files changed, 64 insertions(+), 46 deletions(-) diff --git a/doc/formats/obj.md b/doc/formats/obj.md index a35e9df..d82b068 100644 --- a/doc/formats/obj.md +++ b/doc/formats/obj.md @@ -251,16 +251,24 @@ d: 116 * 100 = 11600. 7368 - 24 = 7344. 5.1 bits / pixel We still don't know what the first 32 bits are all about. Perhaps they can help to explain the differences in putative bpp. -0x002-0x003 changes in step with total number of pixels? +0x002-0x003 changes in step with total number of pixels, but that doesn't seem +to account for the difference. -| ID | 0x2-0x3 | dec LE | Number of pixels | -| -- | ------- | ------ | ---------------- | -| a | 61 01 | 353 | 1 | -| b | 25 01 | 293 | 3312 | -| d | 19 01 | 281 | 11600 | -| c | 16 01 | 278 | 11948 | +Considering sprites with a 1,1 x,y. + +``` + u0 u1 u2 u3 X Y pixeldata +bgtree_m 24 : ee 00 5e 01 01 01 01 1f 00 +blank 0 : 10 01 61 01 01 01 01 fd 00 +transpix 0 : 11 01 3c 01 01 01 01 ae 00 +``` + +Sprites seem to end with a \x00 byte in-general, but we *only* see 0x01 in the +first byte of data for these 1x1 tiles. + +Sprites with `X= 128 Y=63` *almost always* seem to have a u0..u3 of +`d1 00 42 01` with a few exceptions, e.g. `treemac{1,2}.obj` -Not clear what it means. If anything! WH40K_TD.exe loops around "ReadInMissionFLCs", incl. address 0x0041dd10, where it loads in all the .asc and .obj files in a set. diff --git a/scripts/try-uncompress b/scripts/try-uncompress index e24de5a..04264d3 100755 --- a/scripts/try-uncompress +++ b/scripts/try-uncompress @@ -251,55 +251,39 @@ end # * RLE8: https://www.fileformat.info/format/bmp/corion-rle8.htm def decompress(filename) - puts "\nAttempting RLE decompression of #{filename}..." + puts "\nAttempting custom decompression of #{filename}..." obj = load_obj(filename) obj.sprites.each_with_index do |sprite, i| - print "Sprite %02d..."%i + hdr = sprite.header + print "Sprite %02d... x=#{hdr.width} y=#{hdr.height}"%i decompressed = [] data = sprite.data.bytes hdr = sprite.header - (0...hdr.height).each do |i| - # npackets = data.shift(1)[0] # ignore the packet byte - decompressed_line = [] + loop do + break if data.empty? - 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 + type = data.shift(1)[0] + right = data.index(0) + - if decompressed_line.size == hdr.width - print "Done line! " - break - end - - # if npackets > 0 && count == npackets - # print "Done packets! " - # break - # end - - count+=1 + if right.nil? + print "error! end of chunk not found" + break end - raise "Bad length for line #{i}! #{decompressed_line.size} (Expected #{hdr.width})" if decompressed_line.size != hdr.width - decompressed << decompressed_line + rec = data.shift(right) + _ = data.shift(1) # drop the record separator + + decompressed << [ type, rec[0] ] end - puts "Decompressed: #{decompressed.flatten.size} bytes. Sprite pixels: #{hdr.width*hdr.height}" - #display(decompressed.map(&:chr).join("")) + puts ": #{data.size} bytes remaining. Decompressed: #{decompressed.size} bytes. Sprite pixels: #{hdr.width*hdr.height}" + pp decompressed +# display(decompressed.map(&:chr).join("")) end end @@ -318,23 +302,47 @@ def compare(filenames) end end +require 'set' +def correlate(filenames) + objs = filenames.map { |f| load_obj(f) } + + results = Hash.new { |h,k| h[k] = Set.new } + + + objs.each do |obj| + obj.sprites.each do |spr| + results[spr.header.unknown0 & 0xffff] << spr.header.width + end + end + + puts "Unique widths for u0,1" + pp results +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"%[ + puts "%s %03d: %02x %02x %02x %02x %3d %3d %5d %5d %.2f %02x %02x ... %02x"%[ + filename, i, + hdr.unknown0 & 0x000000ff, + (hdr.unknown0 & 0x0000ff00) >> 8, + (hdr.unknown0 & 0x00ff0000) >> 16, + (hdr.unknown0 & 0xff000000) >> 24, hdr.width, hdr.height, px, hdr.size, - (hdr.size*8) / px.to_f + (hdr.size*8) / px.to_f, + spr.data.bytes[0], + spr.data.bytes[1], + spr.data.bytes[-1], ] end end @@ -345,9 +353,11 @@ when "sprites" then when "dump" then ARGV.each { |filename| dump(filename) } when "compare" then - compare(filenames) + compare(ARGV) when "decompress" then ARGV.each { |filename| decompress(filename) } +when "correlate" then + correlate(ARGV) else puts "Unrecognized command #{command}" exit(1)