static void pvrtcGetDecompressedPixels(PVRTCWord P, PVRTCWord Q, PVRTCWord R, PVRTCWord S, ref Pixel32[] pColorData, byte ui8Bpp) { int[][] i32ModulationValues = new int[16][]; for (int i = 0; i < i32ModulationValues.Length; i++) { i32ModulationValues[i] = new int[8]; } int[][] i32ModulationModes = new int[16][]; for (int i = 0; i < i32ModulationModes.Length; i++) { i32ModulationModes[i] = new int[8]; } Pixel128S[] upscaledColorA = new Pixel128S[32]; Pixel128S[] upscaledColorB = new Pixel128S[32]; uint ui32WordWidth = 4; uint ui32WordHeight = 4; if (ui8Bpp == 2) { ui32WordWidth = 8; } unpackModulations(P, 0, 0, i32ModulationValues, i32ModulationModes, ui8Bpp); unpackModulations(Q, (int)ui32WordWidth, 0, i32ModulationValues, i32ModulationModes, ui8Bpp); unpackModulations(R, 0, (int)ui32WordHeight, i32ModulationValues, i32ModulationModes, ui8Bpp); unpackModulations(S, (int)ui32WordWidth, (int)ui32WordHeight, i32ModulationValues, i32ModulationModes, ui8Bpp); interpolateColors(getColorA(P.u32ColorData), getColorA(Q.u32ColorData), getColorA(R.u32ColorData), getColorA(S.u32ColorData), ref upscaledColorA, ui8Bpp); interpolateColors(getColorB(P.u32ColorData), getColorB(Q.u32ColorData), getColorB(R.u32ColorData), getColorB(S.u32ColorData), ref upscaledColorB, ui8Bpp); for (uint y = 0; y < ui32WordHeight; y++) { for (uint x = 0; x < ui32WordWidth; x++) { int mod = getModulationValues(i32ModulationValues, i32ModulationModes, x + ui32WordWidth / 2, y + ui32WordHeight / 2, ui8Bpp); bool punchthroughAlpha = false; if (mod > 10) { punchthroughAlpha = true; mod -= 10; } Pixel128S result; result.red = (upscaledColorA[y * ui32WordWidth + x].red * (8 - mod) + upscaledColorB[y * ui32WordWidth + x].red * mod) / 8; result.green = (upscaledColorA[y * ui32WordWidth + x].green * (8 - mod) + upscaledColorB[y * ui32WordWidth + x].green * mod) / 8; result.blue = (upscaledColorA[y * ui32WordWidth + x].blue * (8 - mod) + upscaledColorB[y * ui32WordWidth + x].blue * mod) / 8; if (punchthroughAlpha) { result.alpha = 0; } else { result.alpha = (upscaledColorA[y * ui32WordWidth + x].alpha * (8 - mod) + upscaledColorB[y * ui32WordWidth + x].alpha * mod) / 8; } if (ui8Bpp == 2) { pColorData[y * ui32WordWidth + x].red = (byte)result.red; pColorData[y * ui32WordWidth + x].green = (byte)result.green; pColorData[y * ui32WordWidth + x].blue = (byte)result.blue; pColorData[y * ui32WordWidth + x].alpha = (byte)result.alpha; } else if (ui8Bpp == 4) { pColorData[y + x * ui32WordHeight].red = (byte)result.red; pColorData[y + x * ui32WordHeight].green = (byte)result.green; pColorData[y + x * ui32WordHeight].blue = (byte)result.blue; pColorData[y + x * ui32WordHeight].alpha = (byte)result.alpha; } } } }
static void unpackModulations(PVRTCWord word, int offsetX, int offsetY, int[][] i32ModulationValues, int[][] i32ModulationModes, byte ui8Bpp) { uint WordModMode = word.u32ColorData & 0x1; uint ModulationBits = word.u32ModulationData; if (ui8Bpp == 2) { if (WordModMode != 0) { if ((ModulationBits & 0x1) != 0) { if ((ModulationBits & (0x1 << 20)) != 0) { WordModMode = 3; } else { WordModMode = 2; } if ((ModulationBits & (0x1 << 21)) != 0) { ModulationBits |= (0x1 << 20); } else { ModulationBits &= ~((uint)0x1 << 20); } } if ((ModulationBits & 0x2) != 0) { ModulationBits |= 0x1; } else { ModulationBits &= ~(uint)0x1; } for (int y = 0; y < 4; y++) { for (int x = 0; x < 8; x++) { i32ModulationModes[x + offsetX][y + offsetY] = (int)WordModMode; if (((x ^ y) & 1) == 0) { i32ModulationValues[x + offsetX][y + offsetY] = (int)(ModulationBits & 3); ModulationBits >>= 2; } } } } else { for (int y = 0; y < 4; y++) { for (int x = 0; x < 8; x++) { i32ModulationModes[x + offsetX][y + offsetY] = (int)WordModMode; if ((ModulationBits & 1) != 0) { i32ModulationValues[x + offsetX][y + offsetY] = 0x3; } else { i32ModulationValues[x + offsetX][y + offsetY] = 0x0; } ModulationBits >>= 1; } } } } else { if (WordModMode != 0) { for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { i32ModulationValues[y + offsetY][x + offsetX] = (int)(ModulationBits & 3); //if (i32ModulationValues==0) {}; don't need to check 0, 0 = 0/8. if (i32ModulationValues[y + offsetY][x + offsetX] == 1) { i32ModulationValues[y + offsetY][x + offsetX] = 4; } else if (i32ModulationValues[y + offsetY][x + offsetX] == 2) { i32ModulationValues[y + offsetY][x + offsetX] = 14; } else if (i32ModulationValues[y + offsetY][x + offsetX] == 3) { i32ModulationValues[y + offsetY][x + offsetX] = 8; } ModulationBits >>= 2; } } } else { for (int y = 0; y < 4; y++) { for (int x = 0; x < 4; x++) { i32ModulationValues[y + offsetY][x + offsetX] = (int)(ModulationBits & 3); i32ModulationValues[y + offsetY][x + offsetX] *= 3; if (i32ModulationValues[y + offsetY][x + offsetX] > 3) { i32ModulationValues[y + offsetY][x + offsetX] -= 1; } ModulationBits >>= 2; } } } } }