diff options
Diffstat (limited to '')
-rw-r--r-- | src/exporter.py | 130 |
1 files changed, 130 insertions, 0 deletions
diff --git a/src/exporter.py b/src/exporter.py new file mode 100644 index 0000000..fec2f86 --- /dev/null +++ b/src/exporter.py @@ -0,0 +1,130 @@ +from common import * +import array +import sys + + +class KPMapExporter: + class LayerExporter: + def __init__(self, layer): + self.layer = layer + + def buildSectors(self, sectors, indices): + # we'll use the cache held by the layer: why reinvent the wheel? + layer.updateCache() + cache = layer.cache + + # first off, get all the info and figure out the sector bounds + layerX, layerY = layer.cacheBasePos + layerWidth, layerHeight = layer.cacheSize + + sectorLeft = layerX / 16 + sectorTop = layerY / 16 + sectorRight = (layerX + layerWidth) / 16 + sectorBottom = (layerY + layerHeight) / 16 + + rawSectors = [] + for i in xrange(sectorBottom - sectorTop + 1): + rawSectors.append([None for j in xrange(sectorRight - sectorLeft + 1)]) + + # copy every tile index over + for srcY in xrange(layerHeight): + srcRow = cache[srcY] + worldY = srcY + layerY + sectorY = worldY / 16 + destY = worldY % 16 + + destRow = rawSectors[sectorY] + + for srcX in xrange(layerX, layerX+layerWidth): + worldX = srcX + layerX + sectorX = worldX / 16 + destX = worldX % 16 + + tile = srcRow[i] + if tile == -1: continue + + destSector = destRow[sectorX] + if destSector is None: + destSector = [[-1 for j in xrange(16)] for i in xrange(16)] + destRow[sectorX] = destSector + + destSector[destY][destX] = tile + + # now add the created sectors to the data + sectorMap = [-1 for i in xrange(len(self.rawSectors))] + + for srcRow, mapRow in zip(self.rawSectors, sectorMap): + for index, sector in enumerate(srcRow): + if sector is not None: + # see if it's a duplicate or not + sectorKey = '|'.join(map(lambda x: ','.join(map(str, x)), sector)) + + try: + mapRow[index] = sectorIndices[sectorKey] + except ValueError: + sectorIndices[sectorKey] = len(sectors) + mapRow[index] = len(sectors) + sectors.append(sector) + + self.sectorBounds = (sectorLeft, sectorTop, sectorRight, sectorBottom) + self.sectorMap = sectorMap + + + + def __init__(self, mapObj): + self.map = mapObj + + self.layers = map(KPMapExporter.LayerExporter, self.map.layers) + + self.archive = WiiArchiveU8() + + def buildAndPack(self, handle=None): + # make the BG data + sectors = [] + sectorIndices = {} + + for layer in self.layers: + layer.buildSectors(sectors, sectorIndices) + + # pack it into the arc + self.archive.resolvePath('/sectors.bin').data = self._packSectorData(sectors) + self.archive.resolvePath('/sectorMaps.bin').data = self._packSectorMaps() + + return self.archive.pack(handle) + + + def _packSectorData(self, sectors): + rowStruct = struct.Struct('>16h') + output = [] + + for sector in sectors: + for row in sector: + output.append(rowStruct.pack(*row)) + + return ''.join(output) + + def _packSectorMaps(self): + offsets = array.array('I') + assert offsets.itemsize == 4 + + currentOffset = len(self.layers) * 4 + + data = [] + + for index, layer in enumerate(self.layers): + offsets.append(currentOffset) + + data.append(struct.pack('>hhhh', *layer.sectorBounds)) + currentOffset += 8 + + first = layer.sectorMap[0] + rowStruct = struct.Struct('>%dh' % len(first)) + for row in layer.sectorMap: + data.append(rowStruct.pack(*row)) + + currentOffset += (len(first) * len(layer.sectorMap) * 2) + + if sys.byteorder == 'little': offsets.byteswap() + return offsets.tostring() + ''.join(data) + + |