From 48d222f017fbf2506497d616c5b54a9f7ef324d3 Mon Sep 17 00:00:00 2001 From: Martin Haye Date: Sun, 5 Jan 2014 16:32:44 -0800 Subject: [PATCH] Working on packing partition files. --- .gitignore | 1 + .../{PackMap => PackPartitions}/build.xml | 6 +- .../{PackMap => PackPartitions}/manifest.mf | 0 .../nbproject/build-impl.xml | 10 +- .../nbproject/genfiles.properties | 2 +- .../nbproject/groovy-build.xml | 0 .../nbproject/project.properties | 6 +- .../nbproject/project.xml | 2 +- .../src/org/demo/PackPartitions.groovy} | 166 ++++++++++++------ 9 files changed, 122 insertions(+), 71 deletions(-) rename Platform/Apple/tools/{PackMap => PackPartitions}/build.xml (94%) rename Platform/Apple/tools/{PackMap => PackPartitions}/manifest.mf (100%) rename Platform/Apple/tools/{PackMap => PackPartitions}/nbproject/build-impl.xml (99%) rename Platform/Apple/tools/{PackMap => PackPartitions}/nbproject/genfiles.properties (92%) rename Platform/Apple/tools/{PackMap => PackPartitions}/nbproject/groovy-build.xml (100%) rename Platform/Apple/tools/{PackMap => PackPartitions}/nbproject/project.properties (95%) rename Platform/Apple/tools/{PackMap => PackPartitions}/nbproject/project.xml (94%) rename Platform/Apple/tools/{PackMap/src/org/demo/PackMap.groovy => PackPartitions/src/org/demo/PackPartitions.groovy} (68%) diff --git a/.gitignore b/.gitignore index 9d0e528d..30c912db 100644 --- a/.gitignore +++ b/.gitignore @@ -14,3 +14,4 @@ # Only check in sample.build.props; each person's build.props will be different. /Platform/Apple/virtual/src/include/build.props /Platform/Apple/tools/A2Copy/build/ +/Platform/Apple/tools/PackPartitions/build/ \ No newline at end of file diff --git a/Platform/Apple/tools/PackMap/build.xml b/Platform/Apple/tools/PackPartitions/build.xml similarity index 94% rename from Platform/Apple/tools/PackMap/build.xml rename to Platform/Apple/tools/PackPartitions/build.xml index 643a4cf7..8a9b232f 100644 --- a/Platform/Apple/tools/PackMap/build.xml +++ b/Platform/Apple/tools/PackPartitions/build.xml @@ -7,8 +7,8 @@ - - Builds, tests, and runs the project PackMap. + + Builds, tests, and runs the project PackPartitions. - + @@ -436,7 +436,7 @@ is divided into following sections: - + @@ -587,7 +587,7 @@ is divided into following sections: - + @@ -879,7 +879,7 @@ is divided into following sections: - + @@ -1361,7 +1361,7 @@ is divided into following sections: - + diff --git a/Platform/Apple/tools/PackMap/nbproject/genfiles.properties b/Platform/Apple/tools/PackPartitions/nbproject/genfiles.properties similarity index 92% rename from Platform/Apple/tools/PackMap/nbproject/genfiles.properties rename to Platform/Apple/tools/PackPartitions/nbproject/genfiles.properties index 22cdbdcd..ef2f6791 100644 --- a/Platform/Apple/tools/PackMap/nbproject/genfiles.properties +++ b/Platform/Apple/tools/PackPartitions/nbproject/genfiles.properties @@ -6,6 +6,6 @@ build.xml.stylesheet.CRC32=8064a381@1.68.1.46 nbproject/build-impl.xml.data.CRC32=69409762 nbproject/build-impl.xml.script.CRC32=12156ac0 nbproject/build-impl.xml.stylesheet.CRC32=cdba79fa@1.68.1.46 -nbproject/groovy-build.xml.data.CRC32=69409762 +nbproject/groovy-build.xml.data.CRC32=f3c1938b nbproject/groovy-build.xml.script.CRC32=629135a5 nbproject/groovy-build.xml.stylesheet.CRC32=919c82d5@1.4.1 diff --git a/Platform/Apple/tools/PackMap/nbproject/groovy-build.xml b/Platform/Apple/tools/PackPartitions/nbproject/groovy-build.xml similarity index 100% rename from Platform/Apple/tools/PackMap/nbproject/groovy-build.xml rename to Platform/Apple/tools/PackPartitions/nbproject/groovy-build.xml diff --git a/Platform/Apple/tools/PackMap/nbproject/project.properties b/Platform/Apple/tools/PackPartitions/nbproject/project.properties similarity index 95% rename from Platform/Apple/tools/PackMap/nbproject/project.properties rename to Platform/Apple/tools/PackPartitions/nbproject/project.properties index a349791a..88f08e9e 100644 --- a/Platform/Apple/tools/PackMap/nbproject/project.properties +++ b/Platform/Apple/tools/PackPartitions/nbproject/project.properties @@ -3,7 +3,7 @@ annotation.processing.enabled.in.editor=false annotation.processing.processors.list= annotation.processing.run.all.processors=true annotation.processing.source.output=${build.generated.sources.dir}/ap-source-output -application.title=PackMap +application.title=PackPartitions application.vendor=mhaye build.classes.dir=${build.dir}/classes build.classes.excludes=**/*.java,**/*.form,**/*.groovy @@ -23,7 +23,7 @@ debug.test.classpath=\ ${run.test.classpath} # This directory is removed when the project is cleaned: dist.dir=dist -dist.jar=${dist.dir}/PackMap.jar +dist.jar=${dist.dir}/PackPartitions.jar dist.javadoc.dir=${dist.dir}/javadoc endorsed.classpath= excludes= @@ -54,7 +54,7 @@ javadoc.splitindex=true javadoc.use=true javadoc.version=false javadoc.windowtitle= -main.class=org.demo.PackMap +main.class=org.demo.PackPartitions manifest.file=manifest.mf meta.inf.dir=${src.dir}/META-INF mkdist.disabled=false diff --git a/Platform/Apple/tools/PackMap/nbproject/project.xml b/Platform/Apple/tools/PackPartitions/nbproject/project.xml similarity index 94% rename from Platform/Apple/tools/PackMap/nbproject/project.xml rename to Platform/Apple/tools/PackPartitions/nbproject/project.xml index a9ba3dfe..551fa545 100644 --- a/Platform/Apple/tools/PackMap/nbproject/project.xml +++ b/Platform/Apple/tools/PackPartitions/nbproject/project.xml @@ -8,7 +8,7 @@ - PackMap + PackPartitions diff --git a/Platform/Apple/tools/PackMap/src/org/demo/PackMap.groovy b/Platform/Apple/tools/PackPartitions/src/org/demo/PackPartitions.groovy similarity index 68% rename from Platform/Apple/tools/PackMap/src/org/demo/PackMap.groovy rename to Platform/Apple/tools/PackPartitions/src/org/demo/PackPartitions.groovy index b1105c78..51b38523 100644 --- a/Platform/Apple/tools/PackMap/src/org/demo/PackMap.groovy +++ b/Platform/Apple/tools/PackPartitions/src/org/demo/PackPartitions.groovy @@ -13,11 +13,21 @@ import java.nio.channels.Channels * * @author mhaye */ -class PackMap +class PackPartitions { def TRANSPARENT_COLOR = 15 - def parseMap(tiles, map) + def TYPE_CODE = 1 + def TYPE_MAP = 2 + def TYPE_IMAGE = 3 + + def images = [:] // img name to img.num, img.buf + def tiles = [:] // tile name to tile.num, tile.buf + def maps = [:] // map name to map.num, map.buf + + def chunks = [] // queue of chunks to be written + + def parseMap(map, tiles) { // Parse each row of the map map.chunk.row.collect @@ -213,25 +223,33 @@ class PackMap } - def writeMap(stream, rows, names) // [ref BigBlue1_50] + def writeMap(buf, rows) // [ref BigBlue1_50] { def width = rows[0].size() def height = rows.size() + def unknown = [] as Set - // Header: one-char code followed by two-byte length - // (length should not include the 5-byte header) - // - def len = width*height - stream.write((int)'M') // for "Map" - stream.write(width) - stream.write(height) - stream.write(len & 0xFF) - stream.write((len>>8) & 0xFF) + // Header: just the width and height + buf.put((byte)width) + buf.put((byte)height) // After the header comes the raw data rows.each { row -> row.each { tile -> - stream.write(names.findIndexOf { it == tile?.@name } + 1) + if (tile?.@obstruction == 'true') { + def name = tile?.@name + if (name in images) + buf.put((byte)images[name].num) + else { + // Alert only once about each unknown name + if (!(name in unknown)) + println "Can't match tile name '$name' to any image; treating as blank." + unknown.add(name) + buf.put((byte)0) + } + } + else + buf.put((byte)0) } } } @@ -248,10 +266,9 @@ class PackMap ((pix2 & 8) << 3) | ((pix1 & 8) << 4); } - def writeImage(stream, image) + def writeImage(buf, image) { - // First, accumulate pixel data for all 5 mip levels plus the orig image - def buf = ByteBuffer.allocate(50000) + // Write pixel data for all 5 mip levels plus the orig image for (def mipLevel in 0..5) { // Process double rows @@ -263,18 +280,71 @@ class PackMap if (mipLevel < 5) image = reduceImage(image) } - def len = buf.position() // len doesn't include 3-byte header - - // Write the header now that we have the length. - stream.write((int)'T') // for 'Texture' - stream.write(len & 0xFF) - stream.write((len>>8) & 0xFF) - - // And copy the data to the output - def tmp = new byte[buf.position()] + } + + def packImage(imgEl) + { + def num = images.size() + 1 + def name = imgEl.@name ?: "img$num" + println "Packing image #$num named '${imgEl.@name}'." + def pixels = parseImage(imgEl) + calcTransparency(pixels) + def buf = ByteBuffer.allocate(50000) + writeImage(buf, pixels) + images[imgEl.@name] = [num:num, buf:buf] + } + + def packMap(mapEl, tileEls) + { + def num = maps.size() + 1 + def name = mapEl.@name ?: "map$num" + println "Packing map #$num named '$name'." + def rows = parseMap(mapEl, tileEls) + def buf = ByteBuffer.allocate(50000) + writeMap(buf, rows) + maps[name] = [num:num, buf:buf] + } + + def writePages(stream, buf) + { + def endPos = buf.position() + def nPages = (endPos + 255) >> 8 + def bytes = new byte[nPages << 8] buf.position(0) - buf.get(tmp) - stream.write(tmp) + buf.get(bytes, 0, endPos) + stream.write(bytes) + } + + def writePartition(stream) + { + // Make a list of all the chunks that will be in the partition + def chunks = [] + maps.values().each { chunks.add([type:TYPE_MAP, num:it.num, buf:it.buf]) } + images.values().each { chunks.add([type:TYPE_IMAGE, num:it.num, buf:it.buf]) } + + // Generate the header chunk. Leave the first byte for the # of pages in the hdr + def hdrBuf = ByteBuffer.allocate(50000) + hdrBuf.put((byte)0) + + // Write the three bytes for each resource + chunks.each { chunk -> + hdrBuf.put((byte)chunk.type) + assert chunk.num >= 1 && chunk.num <= 255 + hdrBuf.put((byte)chunk.num) + def nPages = (chunk.buf.position() + 255) >> 8 + hdrBuf.put((byte)nPages) + } + + // Fix up the first byte to contain the page count of the header + def hdrEnd = hdrBuf.position() + hdrBuf.position(0) + def nPages = (hdrEnd + 255) >> 8 + hdrBuf.put((byte)nPages) + hdrBuf.position(hdrEnd) + + // Finally, write out each chunk, including the header, as 256-byte pages. + writePages(stream, hdrBuf) + chunks.each { writePages(stream, it.buf) } } def pack(xmlPath, binPath) @@ -282,39 +352,19 @@ class PackMap // Open the XML data file produced by Outlaw Editor def dataIn = new XmlParser().parse(xmlPath) - // Locate the map named 'main', or failing that, the first map - def map = dataIn.map.find { it.@name == 'main' } - if (!map) - map = dataIn.map[0] - assert map : "Can't find map 'main' nor any map at all"; - - // Identify all the tiles and make a list of rows - def rows = parseMap(dataIn.tile, map); - - // Determine the unique names of all the 'obstruction' tiles. Those - // are the ones that turn into texture images. + // Pack each image, which has the side-effect of filling in the + // image name map. // - def names = rows.flatten().grep{it?.@obstruction == 'true'}. - collect{it.@name}.sort().unique() + dataIn.image.each { packImage(it) } - println "Parsing images." - def images = names.collect { name -> - parseImage(dataIn.image.find { it.@name == name }) - } - - println "Flood-filling transparency from upper corners." - images.each { calcTransparency(it) } + // Pack each map. This uses the image map filled earlier, and + // fills the map name map. + // + dataIn.map.each { packMap(it, dataIn.tile) } // Ready to start writing the output file. - new File(binPath).withOutputStream { stream -> - println "Writing map." - writeMap(stream, rows, names) - images.eachWithIndex { image, idx -> - println "Writing image #${idx+1}." - writeImage(stream, image) - } - stream.write(0) // properly terminate the file - } + println "Writing output file." + new File(binPath).withOutputStream { stream -> writePartition(stream) } println "Done." } @@ -322,10 +372,10 @@ class PackMap static void main(String[] args) { if (args.size() != 2) { - println "Usage: convert yourMapFile.xml out.bin" + println "Usage: convert yourOutlawFile.xml DISK.PART.0.bin" System.exit(1); } - new PackMap().pack(args[0], args[1]) + new PackPartitions().pack(args[0], args[1]) } }