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)