summaryrefslogtreecommitdiff
path: root/wii/texpalette.cpp
diff options
context:
space:
mode:
authorTreeki <treeki@gmail.com>2012-08-03 05:16:52 +0200
committerTreeki <treeki@gmail.com>2012-08-03 05:16:52 +0200
commit7a183cfa367db01413c001306741d06e1826d077 (patch)
treee50e2e222ddf924e4d868e79ed87a0ced85d01e1 /wii/texpalette.cpp
parentebcc95da4c26369511caa90d89c5ed06e1e4853a (diff)
downloadLayoutStudio-7a183cfa367db01413c001306741d06e1826d077.tar.gz
LayoutStudio-7a183cfa367db01413c001306741d06e1826d077.zip
might as well push all this. a massive amount of changes
Diffstat (limited to 'wii/texpalette.cpp')
-rw-r--r--wii/texpalette.cpp284
1 files changed, 284 insertions, 0 deletions
diff --git a/wii/texpalette.cpp b/wii/texpalette.cpp
new file mode 100644
index 0000000..125454f
--- /dev/null
+++ b/wii/texpalette.cpp
@@ -0,0 +1,284 @@
+#include "texpalette.h"
+
+WiiTexPalette::WiiTexPalette() { }
+
+WiiTexPalette::WiiTexPalette(QDataStream &stream) {
+ quint32 magic;
+ stream >> (quint32&)magic;
+
+ if (magic != 0x20AF30)
+ qWarning() << "WiiTexPalette: tried to load a TPL without the proper magic";
+
+ quint32 textureCount, headerSize;
+ stream >> textureCount;
+ stream >> headerSize;
+
+ qDebug() << textureCount << "textures";
+ textures.resize(textureCount);
+
+ for (int i = 0; i < textureCount; i++) {
+ quint32 textureOffs, paletteOffs;
+ stream >> textureOffs;
+ stream >> paletteOffs;
+
+ int savePos = stream.device()->pos();
+
+ readTexture(stream, textureOffs, paletteOffs, textures[i]);
+
+ stream.device()->seek(savePos);
+ }
+}
+
+static const int TexelWidths[] = {
+ 8, 8, 8, 4, 4, 4, 4, -1, 8, 8, 4
+};
+
+static const int TexelHeights[] = {
+ 8, 4, 4, 4, 4, 4, 4, -1, 8, 4, 4
+};
+
+static const int BitsPerPixel[] = {
+ 4, 8, 8, 16, 16, 16, 32, -1, 8, 16
+};
+
+// This bit shamelessly stolen from Dolphin, but it didn't QUITE work right...
+/*inline uchar _3to8(uchar v) { return (v << 5) | (v << 2) | (v >> 1); }
+inline uchar _4to8(uchar v) { return (v << 4) | v; }
+inline uchar _5to8(uchar v) { return (v << 3) | (v << 2); }
+inline uchar _6to8(uchar v) { return (v << 2) | (v >> 4); }*/
+inline uchar _3to8(uchar v) { return (v << 5); }
+inline uchar _4to8(uchar v) { return (v << 4); }
+inline uchar _5to8(uchar v) { return (v << 3); }
+inline uchar _6to8(uchar v) { return (v << 2); }
+
+void WiiTexPalette::readTexture(QDataStream &in, int textureOffs, int paletteOffs, WiiTPLTexture &tex) {
+ in.device()->seek(textureOffs);
+
+ quint16 width, height;
+ quint32 rawFormat, dataOffs, rawWrapS, rawWrapT, rawMinFilter, rawMagFilter;
+ quint8 rawEdgeLODEnable;
+
+ in >> height;
+ in >> width;
+ in >> rawFormat;
+ in >> dataOffs;
+ in >> rawWrapS;
+ in >> rawWrapT;
+ in >> rawMinFilter;
+ in >> rawMagFilter;
+ in >> tex.lodBias;
+ in >> rawEdgeLODEnable;
+ in >> tex.minLOD;
+ in >> tex.maxLOD;
+
+ tex.format = (GX::TextureFormat)rawFormat;
+ tex.wrapS = (GX::WrapType)rawWrapS;
+ tex.wrapT = (GX::WrapType)rawWrapT;
+ tex.minFilter = (GX::TextureFilter)rawMinFilter;
+ tex.magFilter = (GX::TextureFilter)rawMagFilter;
+ tex.edgeLODEnable = (rawEdgeLODEnable > 0);
+
+ bool formatValid = (
+ (rawFormat <= 6) ||
+ (rawFormat >= 8 && rawFormat <= 10) ||
+ rawFormat == 14);
+
+ if (!formatValid) {
+ qWarning("unknown texture format (%d)", rawFormat);
+ return;
+ }
+
+ tex.image = QImage(width, height, QImage::Format_ARGB32);
+
+ int texelWidth = TexelWidths[rawFormat];
+ int texelHeight = TexelHeights[rawFormat];
+ int bpp = BitsPerPixel[rawFormat];
+
+ // how much needs to be added on to get this texture aligned?
+ int padWidth = width % texelWidth;
+ int padHeight = height % texelHeight;
+
+ // get the fully padded width
+ int paddedWidth = width + ((padWidth > 0) ? (texelWidth - padWidth) : 0);
+ int paddedHeight = height + ((padHeight > 0) ? (texelHeight - padHeight) : 0);
+
+ int texDataSize = (paddedWidth * paddedHeight * bpp) / 8;
+
+ // decode the thing
+ in.device()->seek(dataOffs);
+
+ QImage &image = tex.image;
+
+ switch (tex.format) {
+ case GX::I4:
+ {
+ for (int texelY = 0; texelY < paddedHeight; texelY += 8) {
+ for (int texelX = 0; texelX < paddedWidth; texelX += 8) {
+ for (int y = texelY; y < (texelY + 8); y++) {
+ QRgb *scanline = (QRgb*)image.scanLine(y);
+
+ for (int x = texelX; x < (texelX + 8); x += 2) {
+ quint8 v;
+ in >> v;
+
+ if (x < width && y < height) {
+ int _v = _4to8(v >> 4);
+ scanline[x] = qRgb(_v, _v, _v);
+ }
+ if ((x+1) < width && y < height) {
+ int _v = _4to8(v & 0xF);
+ scanline[x+1] = qRgb(_v, _v, _v);
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case GX::I8:
+ {
+ for (int texelY = 0; texelY < paddedHeight; texelY += 4) {
+ for (int texelX = 0; texelX < paddedWidth; texelX += 8) {
+ for (int y = texelY; y < (texelY + 4); y++) {
+ QRgb *scanline = (QRgb*)image.scanLine(y);
+
+ for (int x = texelX; x < (texelX + 8); x++) {
+ quint8 v;
+ in >> v;
+
+ if (x < width && y < height)
+ scanline[x] = qRgb(v, v, v);
+ }
+ }
+ }
+ }
+ }
+ break;
+ case GX::IA4:
+ {
+ for (int texelY = 0; texelY < paddedHeight; texelY += 4) {
+ for (int texelX = 0; texelX < paddedWidth; texelX += 8) {
+ for (int y = texelY; y < (texelY + 4); y++) {
+ QRgb *scanline = (QRgb*)image.scanLine(y);
+
+ for (int x = texelX; x < (texelX + 8); x++) {
+ quint8 v;
+ in >> v;
+
+ if (x < width && y < height) {
+ int _i = _4to8(v & 0xF);
+ int _a = _4to8(v >> 4);
+ scanline[x] = qRgba(_i, _i, _i, _a);
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case GX::IA8:
+ {
+ for (int texelY = 0; texelY < paddedHeight; texelY += 4) {
+ for (int texelX = 0; texelX < paddedWidth; texelX += 4) {
+ for (int y = texelY; y < (texelY + 4); y++) {
+ QRgb *scanline = (QRgb*)image.scanLine(y);
+
+ for (int x = texelX; x < (texelX + 4); x++) {
+ quint16 v;
+ in >> v;
+
+ if (x < width && y < height)
+ scanline[x] = qRgba((v&0xFF00)>>8, (v&0xFF00)>>8, (v&0xFF00)>>8, v&0xFF);
+ }
+ }
+ }
+ }
+ }
+ break;
+ case GX::RGB565:
+ {
+ for (int texelY = 0; texelY < paddedHeight; texelY += 4) {
+ for (int texelX = 0; texelX < paddedWidth; texelX += 4) {
+ for (int y = texelY; y < (texelY + 4); y++) {
+ QRgb *scanline = (QRgb*)image.scanLine(y);
+
+ for (int x = texelX; x < (texelX + 4); x++) {
+ quint16 v;
+ in >> v;
+
+ if (x < width && y < height) {
+ scanline[x] = qRgb(
+ _5to8((v >> 11) & 0x1F),
+ _6to8((v >> 5) & 0x3F),
+ _5to8(v & 0x1F));
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case GX::RGB5A3:
+ {
+ for (int texelY = 0; texelY < paddedHeight; texelY += 4) {
+ for (int texelX = 0; texelX < paddedWidth; texelX += 4) {
+ for (int y = texelY; y < (texelY + 4); y++) {
+ QRgb *scanline = (QRgb*)image.scanLine(y);
+
+ for (int x = texelX; x < (texelX + 4); x++) {
+ quint16 v;
+ in >> v;
+
+ if (x < width && y < height) {
+ if (v & 0x8000) {
+ scanline[x] = qRgb(
+ _5to8((v >> 10) & 0x1F),
+ _5to8((v >> 5) & 0x1F),
+ _5to8(v & 0x1F));
+ } else {
+ scanline[x] = qRgba(
+ _4to8((v >> 8) & 0xF),
+ _4to8((v >> 4) & 0xF),
+ _4to8(v & 0xF),
+ _3to8((v >> 12) & 0x7));
+ }
+ }
+ }
+ }
+ }
+ }
+ }
+ break;
+ case GX::RGBA8:
+ {
+ QByteArray texel1(32, 0), texel2(32, 0);
+
+ for (int texelY = 0; texelY < paddedHeight; texelY += 4) {
+ for (int texelX = 0; texelX < paddedWidth; texelX += 4) {
+ in.readRawData(texel1.data(), 32);
+ in.readRawData(texel2.data(), 32);
+
+ int offs = 0;
+
+ for (int y = texelY; y < (texelY + 4); y++) {
+ QRgb *scanline = (QRgb*)image.scanLine(y);
+
+ for (int x = texelX; x < (texelX + 4); x++) {
+ if (x < width && y < height) {
+ scanline[x] = qRgba(texel1.at(offs+1), texel2.at(offs), texel2.at(offs+1), texel1.at(offs));
+ }
+ offs += 2;
+ }
+ }
+ }
+ }
+ }
+ break;
+ default:
+ qWarning("unhandled texture format (%d)", rawFormat);
+ }
+}
+
+
+void WiiTexPalette::writeToDataStream(QDataStream &out) const {
+}