From a86e1f9310d7428bc99b65a2b0fbb0e36cda40a4 Mon Sep 17 00:00:00 2001 From: Treeki Date: Tue, 4 Dec 2012 03:44:19 +0100 Subject: added RGBA8 tileset support --- Koopuzzle/Koopuzzle.py | 92 ++++++++++++++++++++++++++++++-------------------- src/exporter.py | 26 ++++++++++++-- 2 files changed, 78 insertions(+), 40 deletions(-) diff --git a/Koopuzzle/Koopuzzle.py b/Koopuzzle/Koopuzzle.py index 8672d57..cb63412 100755 --- a/Koopuzzle/Koopuzzle.py +++ b/Koopuzzle/Koopuzzle.py @@ -838,7 +838,7 @@ class PiecesModel(QtCore.QAbstractListModel): ################## Python-based RGB5a3 Decoding code from my BRFNT program ################## -def RGB4A3Decode(tex): +def RGB5A3Decode(tex): dest = QtGui.QImage(896,448,QtGui.QImage.Format_ARGB32) dest.fill(QtCore.Qt.transparent) @@ -856,19 +856,16 @@ def RGB4A3Decode(tex): # newpixel = (int(tex[i]) << 8) | int(tex[i+1]) - # if(newpixel >= 0x8000): # Check if it's RGB555 - # red = ((newpixel >> 10) & 0x1F) * 255 / 0x1F - # green = ((newpixel >> 5) & 0x1F) * 255 / 0x1F - # blue = (newpixel & 0x1F) * 255 / 0x1F - # alpha = 0xFF - - # else: # If not, it's RGB4A3 - - # IT'S ALWAYS FUCKING RGB4A3 - who makes a tileset without alpha?! - alpha = ((newpixel & 0x7000) >> 12) * 255 / 0x7 - red = ((newpixel & 0xF00) >> 8) * 255 / 0xF - green = ((newpixel & 0xF0) >> 4) * 255 / 0xF - blue = (newpixel & 0xF) * 255 / 0xF + if(newpixel >= 0x8000): # Check if it's RGB555 + red = ((newpixel >> 10) & 0x1F) * 255 / 0x1F + green = ((newpixel >> 5) & 0x1F) * 255 / 0x1F + blue = (newpixel & 0x1F) * 255 / 0x1F + alpha = 0xFF + else: # If not, it's RGB4A3 + alpha = ((newpixel & 0x7000) >> 12) * 255 / 0x7 + red = ((newpixel & 0xF00) >> 8) * 255 / 0xF + green = ((newpixel & 0xF0) >> 4) * 255 / 0xF + blue = (newpixel & 0xF) * 255 / 0xF argb = (blue) | (green << 8) | (red << 16) | (alpha << 24) dest.setPixel(xpixel, ypixel, argb) @@ -876,7 +873,7 @@ def RGB4A3Decode(tex): return dest -def RGB4A3Encode(tex): +def RGB5A3Encode(tex, force4A3=True): destBuffer = create_string_buffer(896*tex.height()*2) shortstruct = struct.Struct('>H') @@ -894,29 +891,45 @@ def RGB4A3Encode(tex): g = (pixel >> 8) & 0xFF b = pixel & 0xFF - # if a < 245: #RGB4A3 - - # IT'S ALWAYS FUCKING RGB4A3 - who makes a tileset without alpha?! - alpha = a/32 - red = r/16 - green = g/16 - blue = b/16 + if a < 245 or force4A3: #RGB4A3 + alpha = a/32 + red = r/16 + green = g/16 + blue = b/16 + rgbDAT = (blue) | (green << 4) | (red << 8) | (alpha << 12) + else: # RGB555 + red = r/8 + green = g/8 + blue = b/8 + rgbDAT = (blue) | (green << 5) | (red << 10) | (0x8000) # 0rrrrrgggggbbbbb - rgbDAT = (blue) | (green << 4) | (red << 8) | (alpha << 12) - - # else: # RGB555 - # red = r/8 - # green = g/8 - # blue = b/8 - - # rgbDAT = (blue) | (green << 5) | (red << 10) | (0x8000) # 0rrrrrgggggbbbbb - shortstruct.pack_into(destBuffer, offset, rgbDAT) offset += 2 return destBuffer.raw +def RGBA8Encode(tex): + destBuffer = create_string_buffer(896*tex.height()*4) + + shortstruct = struct.Struct('>H') + offset = 0 + + for ytile in xrange(0, tex.height(), 4): + for xtile in xrange(0, 896, 4): + for ypixel in xrange(ytile, ytile + 4): + for xpixel in xrange(xtile, xtile + 4): + + pixel = tex.pixel(xpixel, ypixel) + + shortstruct.pack_into(destBuffer, offset, pixel>>16) + shortstruct.pack_into(destBuffer, offset+32, pixel&0xFFFF) + offset += 2 + offset += 32 + + return destBuffer.raw + + ############################################################################################# ############ Main Window Class. Takes care of menu functions and widget creation ############ @@ -1023,7 +1036,7 @@ class MainWindow(QtGui.QMainWindow): QtGui.QMessageBox.warning(None, 'Error', 'Error - the necessary files were not found.\n\nNot a valid Koopatlas tileset, sadly.') return - dest = RGB4A3Decode(Image) + dest = RGB5A3Decode(Image) self.tileImage = QtGui.QPixmap.fromImage(dest) @@ -1167,6 +1180,8 @@ class MainWindow(QtGui.QMainWindow): # Prepare tiles, objects, object metadata, and textures and stuff into buffers. + self.usesRGBA8 = ('RGBA8' in name) + textureBuffer = self.PackTexture() optTextureBuffer, optMappings = self.PackOptimisedTexture() objectBuffers = self.PackObjects() @@ -1209,11 +1224,11 @@ class MainWindow(QtGui.QMainWindow): mapping[i] = len(sortedTiles) sortedTiles.append(img) - tex = self.PackTexture(sortedTiles) + tex = self.PackTexture(sortedTiles, 'rgba8' if self.usesRGBA8 else 'real_rgb5a3') maps = ','.join(map(str, mapping)) return tex, maps - def PackTexture(self, imageList=None): + def PackTexture(self, imageList=None, mode='standard'): if imageList is None: imageList = map(lambda x: x.image, Tileset.tiles) usesPixmap = isinstance(imageList[0], QtGui.QPixmap) @@ -1297,9 +1312,12 @@ class MainWindow(QtGui.QMainWindow): painter.end() tex.save('beef.png') - dest = RGB4A3Encode(tex) - - return dest + if mode == 'rgba8': + return RGBA8Encode(tex) + elif mode == 'real_rgb5a3': + return RGB5A3Encode(tex, False) + else: + return RGB5A3Encode(tex) diff --git a/src/exporter.py b/src/exporter.py index f6798c7..b1afaaa 100644 --- a/src/exporter.py +++ b/src/exporter.py @@ -421,7 +421,11 @@ class KPMapExporter: except ValueError: convertedWorldID = ord(world.worldID) - ord('A') + 10 - data += struct.pack('>BBBB BBBB BBBB BBBB BBBB BBBB hbb BBB B', + parseCrap = world.titleScreenID.split('-') + tsW = int(parseCrap[0]) + tsL = int(parseCrap[1]) + + data += struct.pack('>BBBB BBBB BBBB BBBB BBBB BBBB hbb BBB BB BBB', fst1[0],fst1[1],fst1[2],fst1[3], fst2[0],fst2[1],fst2[2],fst2[3], fsh1[0],fsh1[1],fsh1[2],fsh1[3], @@ -431,7 +435,8 @@ class KPMapExporter: htf[0],htf[1],htf[2], world.uniqueKey, world.musicTrackID, convertedWorldID, - 0 + tsW - 1, tsL - 1, + 0, 0, 0 ) # now that we're almost done... pack the strings @@ -468,7 +473,10 @@ class KPMapExporter: struct.pack_into('>ii', data, tsInfoOffsetInHeader, len(tilesets), len(data)) for setname in tilesets: offsets[('tileset', setname)] = len(data) - data += self._buildGXTexObjRGB5A3(896, 448, offsets[setname]) + if 'RGBA8' in setname: + data += self._buildGXTexObjRGBA8(896, 448, offsets[setname]) + else: + data += self._buildGXTexObjRGB5A3(896, 448, offsets[setname]) for tex in textures: offsets[tex] = len(data) @@ -550,6 +558,18 @@ class KPMapExporter: 0x0202 ) + def _buildGXTexObjRGBA8(self, width, height, imgOffset): + # Format: RGBA8 (6) + # Wrap: CLAMP (0) + return struct.pack('>IIIIIIIHH', + 0x90, 0, + (0x600000 | ((height - 1) << 10) | (width - 1)), + 0x10000000 + imgOffset, # (imgptr >> 5) + 0, 0, 0, + (((width + 3) / 4) * ((height + 3) / 4)) & 0x7FFF, + 0x0202 + ) + def _packSectorData(self, sectors): rowStruct = struct.Struct('>16h') -- cgit v1.2.3