Permalink
Cannot retrieve contributors at this time
executable file
1900 lines (1700 sloc)
77.4 KB
| // This is an open source non-commercial project. Dear PVS-Studio, please check it. | |
| // PVS-Studio Static Code Analyzer for C, C++ and C#: http://www.viva64.com | |
| // ****************************************************************** | |
| // * | |
| // * .,-::::: .,:: .::::::::. .,:: .: | |
| // * ,;;;'````' `;;;, .,;; ;;;'';;' `;;;, .,;; | |
| // * [[[ '[[,,[[' [[[__[[\. '[[,,[[' | |
| // * $$$ Y$$$P $$""""Y$$ Y$$$P | |
| // * `88bo,__,o, oP"``"Yo, _88o,,od8P oP"``"Yo, | |
| // * "YUMMMMMP",m" "Mm,""YUMMMP" ,m" "Mm, | |
| // * | |
| // * Cxbx->Win32->CxbxKrnl->EmuD3D8->Convert.cpp | |
| // * | |
| // * This file is part of the Cxbx project. | |
| // * | |
| // * Cxbx and Cxbe are free software; you can redistribute them | |
| // * and/or modify them under the terms of the GNU General Public | |
| // * License as published by the Free Software Foundation; either | |
| // * version 2 of the license, or (at your option) any later version. | |
| // * | |
| // * This program is distributed in the hope that it will be useful, | |
| // * but WITHOUT ANY WARRANTY; without even the implied warranty of | |
| // * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
| // * GNU General Public License for more details. | |
| // * | |
| // * You should have recieved a copy of the GNU General Public License | |
| // * along with this program; see the file COPYING. | |
| // * If not, write to the Free Software Foundation, Inc., | |
| // * 59 Temple Place - Suite 330, Bostom, MA 02111-1307, USA. | |
| // * | |
| // * (c) 2002-2004 Aaron Robinson <caustik@caustik.com> | |
| // * Kingofc <kingofc@freenet.de> | |
| // * | |
| // * All rights reserved | |
| // * | |
| // ****************************************************************** | |
| #define _XBOXKRNL_DEFEXTRN_ | |
| #include "CxbxKrnl/Emu.h" | |
| #include "CxbxKrnl/EmuXTL.h" | |
| #include "Convert.h" | |
| // About format color components: | |
| // A = alpha, byte : 0 = fully opaque, 255 = fully transparent | |
| // X = ignore these component bits | |
| // R = red | |
| // G = green | |
| // B = blue | |
| // L = luminance, byte : 0 = pure black ARGB(1, 0,0,0) to 255 = pure white ARGB(1,255,255,255) | |
| // P = pallete | |
| enum _ComponentEncoding { | |
| NoCmpnts = 0, // Format doesn't contain any component (ARGB/QWVU) | |
| A1R5G5B5, | |
| X1R5G5B5, // NOTE : A=255 | |
| A4R4G4B4, | |
| __R5G6B5, // NOTE : A=255 | |
| A8R8G8B8, | |
| X8R8G8B8, // NOTE : A=255 | |
| ____R8B8, // NOTE : A takes R, G takes B | |
| ____G8B8, // NOTE : A takes G, R takes B | |
| ______A8, // TEST : R=G=B= 255 | |
| __R6G5B5, // NOTE : A=255 | |
| R5G5B5A1, | |
| R4G4B4A4, | |
| A8B8G8R8, | |
| B8G8R8A8, | |
| R8G8B8A8, | |
| ______L8, // NOTE : A=255, R=G=B= L | |
| _____AL8, // NOTE : A=R=G=B= L | |
| _____L16, // NOTE : Actually G8B8, with A=R=255 | |
| ____A8L8, // NOTE : R=G=B= L | |
| ____DXT1, | |
| ____DXT3, | |
| ____DXT5, | |
| ______P8, | |
| ____YUY2, | |
| ____UYVY, | |
| }; | |
| // Conversion functions copied from libyuv | |
| // See https://chromium.googlesource.com/libyuv/libyuv/+/master/source/row_common.cc | |
| void RGB565ToARGBRow_C(const uint8* src_rgb565, uint8* dst_argb, int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 b = src_rgb565[0] & 0x1f; | |
| uint8 g = (src_rgb565[0] >> 5) | ((src_rgb565[1] & 0x07) << 3); | |
| uint8 r = src_rgb565[1] >> 3; | |
| dst_argb[0] = (b << 3) | (b >> 2); | |
| dst_argb[1] = (g << 2) | (g >> 4); | |
| dst_argb[2] = (r << 3) | (r >> 2); | |
| dst_argb[3] = 255u; | |
| dst_argb += 4; | |
| src_rgb565 += 2; | |
| } | |
| } | |
| void ARGB1555ToARGBRow_C(const uint8* src_argb1555, | |
| uint8* dst_argb, | |
| int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 b = src_argb1555[0] & 0x1f; | |
| uint8 g = (src_argb1555[0] >> 5) | ((src_argb1555[1] & 0x03) << 3); | |
| uint8 r = (src_argb1555[1] & 0x7c) >> 2; | |
| uint8 a = src_argb1555[1] >> 7; | |
| dst_argb[0] = (b << 3) | (b >> 2); | |
| dst_argb[1] = (g << 3) | (g >> 2); | |
| dst_argb[2] = (r << 3) | (r >> 2); | |
| dst_argb[3] = -a; | |
| dst_argb += 4; | |
| src_argb1555 += 2; | |
| } | |
| } | |
| void ARGB4444ToARGBRow_C(const uint8* src_argb4444, | |
| uint8* dst_argb, | |
| int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 b = src_argb4444[0] & 0x0f; | |
| uint8 g = src_argb4444[0] >> 4; | |
| uint8 r = src_argb4444[1] & 0x0f; | |
| uint8 a = src_argb4444[1] >> 4; | |
| dst_argb[0] = (b << 4) | b; | |
| dst_argb[1] = (g << 4) | g; | |
| dst_argb[2] = (r << 4) | r; | |
| dst_argb[3] = (a << 4) | a; | |
| dst_argb += 4; | |
| src_argb4444 += 2; | |
| } | |
| } | |
| // Cxbx color component conversion functions | |
| void X1R5G5B5ToARGBRow_C(const uint8* src_x1r5g5b5, uint8* dst_argb, | |
| int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 b = src_x1r5g5b5[0] & 0x1f; | |
| uint8 g = (src_x1r5g5b5[0] >> 5) | ((src_x1r5g5b5[1] & 0x03) << 3); | |
| uint8 r = (src_x1r5g5b5[1] & 0x7c) >> 2; | |
| dst_argb[0] = (b << 3) | (b >> 2); | |
| dst_argb[1] = (g << 3) | (g >> 2); | |
| dst_argb[2] = (r << 3) | (r >> 2); | |
| dst_argb[3] = 255u; | |
| dst_argb += 4; | |
| src_x1r5g5b5 += 2; | |
| } | |
| } | |
| void A8R8G8B8ToARGBRow_C(const uint8* src_a8r8g8b8, uint8* dst_argb, int width) { | |
| memcpy(dst_argb, src_a8r8g8b8, width * sizeof(XTL::D3DCOLOR)); // Cxbx pass-through | |
| } | |
| void X8R8G8B8ToARGBRow_C(const uint8* src_x8r8g8b8, uint8* dst_argb, int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 b = src_x8r8g8b8[0]; | |
| uint8 g = src_x8r8g8b8[1]; | |
| uint8 r = src_x8r8g8b8[2]; | |
| dst_argb[0] = b; | |
| dst_argb[1] = g; | |
| dst_argb[2] = r; | |
| dst_argb[3] = 255u; | |
| dst_argb += 4; | |
| src_x8r8g8b8 += 4; | |
| } | |
| } | |
| void ____R8B8ToARGBRow_C(const uint8* src_r8b8, uint8* dst_argb, int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 b = src_r8b8[0]; | |
| uint8 r = src_r8b8[1]; | |
| dst_argb[0] = b; | |
| dst_argb[1] = b; | |
| dst_argb[2] = r; | |
| dst_argb[3] = r; | |
| dst_argb += 4; | |
| src_r8b8 += 2; | |
| } | |
| } | |
| void ____G8B8ToARGBRow_C(const uint8* src_g8b8, uint8* dst_argb, int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 b = src_g8b8[0]; | |
| uint8 g = src_g8b8[1]; | |
| dst_argb[0] = b; | |
| dst_argb[1] = g; | |
| dst_argb[2] = b; | |
| dst_argb[3] = g; | |
| dst_argb += 4; | |
| src_g8b8 += 2; | |
| } | |
| } | |
| void ______A8ToARGBRow_C(const uint8* src_a8, uint8* dst_argb, int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 a = src_a8[0]; | |
| dst_argb[0] = 255u; | |
| dst_argb[1] = 255u; | |
| dst_argb[2] = 255u; | |
| dst_argb[3] = a; | |
| dst_argb += 4; | |
| src_a8 += 1; | |
| } | |
| } | |
| void __R6G5B5ToARGBRow_C(const uint8* src_r6g5b5, uint8* dst_argb, int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 b = src_r6g5b5[0] & 0x1f; | |
| uint8 g = (src_r6g5b5[0] >> 5) | ((src_r6g5b5[1] & 0x03) << 3); | |
| uint8 r = src_r6g5b5[1] >> 2; | |
| dst_argb[0] = (b << 3) | (b >> 2); | |
| dst_argb[1] = (g << 3) | (g >> 2); | |
| dst_argb[2] = (r << 2) | (r >> 4); | |
| dst_argb[3] = 255u; | |
| dst_argb += 4; | |
| src_r6g5b5 += 2; | |
| } | |
| } | |
| void R5G5B5A1ToARGBRow_C(const uint8* src_r5g5b5a1, uint8* dst_argb, int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 a = src_r5g5b5a1[0] & 1; | |
| uint8 b = (src_r5g5b5a1[0] & 0x3e) >> 1; | |
| uint8 g = (src_r5g5b5a1[0] >> 6) | ((src_r5g5b5a1[1] & 0x07) << 2); | |
| uint8 r = (src_r5g5b5a1[1] & 0xf8) >> 3; | |
| dst_argb[0] = (b << 3) | (b >> 2); | |
| dst_argb[1] = (g << 3) | (g >> 2); | |
| dst_argb[2] = (r << 3) | (r >> 2); | |
| dst_argb[3] = -a; | |
| dst_argb += 4; | |
| src_r5g5b5a1 += 2; | |
| } | |
| } | |
| void R4G4B4A4ToARGBRow_C(const uint8* src_r4g4b4a4, uint8* dst_argb, int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 a = src_r4g4b4a4[0] & 0x0f; | |
| uint8 b = src_r4g4b4a4[0] >> 4; | |
| uint8 g = src_r4g4b4a4[1] & 0x0f; | |
| uint8 r = src_r4g4b4a4[1] >> 4; | |
| dst_argb[0] = (b << 4) | b; | |
| dst_argb[1] = (g << 4) | g; | |
| dst_argb[2] = (r << 4) | r; | |
| dst_argb[3] = (a << 4) | a; | |
| dst_argb += 4; | |
| src_r4g4b4a4 += 2; | |
| } | |
| } | |
| void A8B8G8R8ToARGBRow_C(const uint8* src_a8b8g8r8, uint8* dst_argb, int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 r = src_a8b8g8r8[0]; | |
| uint8 g = src_a8b8g8r8[1]; | |
| uint8 b = src_a8b8g8r8[3]; | |
| uint8 a = src_a8b8g8r8[4]; | |
| dst_argb[0] = b; | |
| dst_argb[1] = g; | |
| dst_argb[2] = r; | |
| dst_argb[3] = a; | |
| dst_argb += 4; | |
| src_a8b8g8r8 += 4; | |
| } | |
| } | |
| void B8G8R8A8ToARGBRow_C(const uint8* src_b8g8r8a8, uint8* dst_argb, int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 a = src_b8g8r8a8[0]; | |
| uint8 r = src_b8g8r8a8[1]; | |
| uint8 g = src_b8g8r8a8[3]; | |
| uint8 b = src_b8g8r8a8[4]; | |
| dst_argb[0] = b; | |
| dst_argb[1] = g; | |
| dst_argb[2] = r; | |
| dst_argb[3] = a; | |
| dst_argb += 4; | |
| src_b8g8r8a8 += 4; | |
| } | |
| } | |
| void R8G8B8A8ToARGBRow_C(const uint8* src_r8g8b8a8, uint8* dst_argb, int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 a = src_r8g8b8a8[0]; | |
| uint8 b = src_r8g8b8a8[1]; | |
| uint8 g = src_r8g8b8a8[3]; | |
| uint8 r = src_r8g8b8a8[4]; | |
| dst_argb[0] = b; | |
| dst_argb[1] = g; | |
| dst_argb[2] = r; | |
| dst_argb[3] = a; | |
| dst_argb += 4; | |
| src_r8g8b8a8 += 4; | |
| } | |
| } | |
| void ______L8ToARGBRow_C(const uint8* src_l8, uint8* dst_argb, int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 l = src_l8[0]; | |
| dst_argb[0] = l; | |
| dst_argb[1] = l; | |
| dst_argb[2] = l; | |
| dst_argb[3] = 255u; | |
| dst_argb += 4; | |
| src_l8 += 1; | |
| } | |
| } | |
| void _____AL8ToARGBRow_C(const uint8* src_al8, uint8* dst_argb, int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 l = src_al8[0]; | |
| dst_argb[0] = l; | |
| dst_argb[1] = l; | |
| dst_argb[2] = l; | |
| dst_argb[3] = l; | |
| dst_argb += 4; | |
| src_al8 += 1; | |
| } | |
| } | |
| void _____L16ToARGBRow_C(const uint8* src_l16, uint8* dst_argb, int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 b = src_l16[0]; | |
| uint8 g = src_l16[1]; | |
| dst_argb[0] = b; | |
| dst_argb[1] = g; | |
| dst_argb[2] = 255u; | |
| dst_argb[3] = 255u; | |
| dst_argb += 4; | |
| src_l16 += 2; | |
| } | |
| } | |
| void ____A8L8ToARGBRow_C(const uint8* src_a8l8, uint8* dst_argb, int width) { | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 l = src_a8l8[0]; | |
| uint8 a = src_a8l8[1]; | |
| dst_argb[0] = l; | |
| dst_argb[1] = l; | |
| dst_argb[2] = l; | |
| dst_argb[3] = a; | |
| dst_argb += 4; | |
| src_a8l8 += 2; | |
| } | |
| } | |
| typedef struct TRGB32 | |
| { | |
| unsigned char B; | |
| unsigned char G; | |
| unsigned char R; | |
| unsigned char A; | |
| } TRGB32; | |
| // DXT1 info (MSDN Block Compression) : https://msdn.microsoft.com/en-us/library/bb694531.aspx | |
| // https://msdn.microsoft.com/en-us/library/windows/desktop/bb147243(v=vs.85).aspx | |
| void ____DXT1ToARGBRow_C(const uint8* data, uint8* dst_argb, int width) { | |
| int dst_pitch = *(int*)dst_argb; // dirty hack to avoid another argument | |
| int x; | |
| for (x = 0; x < width; x+=4) { | |
| // Read two 16-bit pixels | |
| uint16 color_0 = data[0] | (data[1] << 8); | |
| uint16 color_1 = data[2] | (data[3] << 8); | |
| // Read 5+6+5 bit color channels | |
| uint8 b0 = color_0 & 0x1f; | |
| uint8 g0 = (color_0 >> 5) & 0x3f; | |
| uint8 r0 = color_0 >> 11; | |
| uint8 b1 = color_1 & 0x1f; | |
| uint8 g1 = (color_1 >> 5) & 0x3f; | |
| uint8 r1 = color_1 >> 11; | |
| // Build first half of RGB32 color map (converting 5+6+5 to 8+8+8): | |
| TRGB32 colormap[4]; | |
| colormap[0].B = (b0 << 3) | (b0 >> 2); | |
| colormap[0].G = (g0 << 2) | (g0 >> 4); | |
| colormap[0].R = (r0 << 3) | (r0 >> 2); | |
| colormap[0].A = 255u; | |
| colormap[1].B = (b1 << 3) | (b1 >> 2); | |
| colormap[1].G = (g1 << 2) | (g1 >> 4); | |
| colormap[1].R = (r1 << 3) | (r1 >> 2); | |
| colormap[1].A = 255u; | |
| // Build second half of RGB32 color map : | |
| if (color_0 > color_1) | |
| { | |
| // Make up new color : 2/3 A + 1/3 B : | |
| colormap[2].B = (uint8)((2 * colormap[0].B + 1 * colormap[1].B + 2) / 3); | |
| colormap[2].G = (uint8)((2 * colormap[0].G + 1 * colormap[1].G + 2) / 3); | |
| colormap[2].R = (uint8)((2 * colormap[0].R + 1 * colormap[1].R + 2) / 3); | |
| colormap[2].A = 255u; | |
| // Make up new color : 1/3 A + 2/3 B : | |
| colormap[3].B = (uint8)((1 * colormap[0].B + 2 * colormap[1].B + 2) / 3); | |
| colormap[3].G = (uint8)((1 * colormap[0].G + 2 * colormap[1].G + 2) / 3); | |
| colormap[3].R = (uint8)((1 * colormap[0].R + 2 * colormap[1].R + 2) / 3); | |
| colormap[3].A = 255u; | |
| } | |
| else | |
| { | |
| // Make up one new color : 1/2 A + 1/2 B : | |
| colormap[2].B = (uint8)((colormap[0].B + colormap[1].B + 1) / 2); | |
| colormap[2].G = (uint8)((colormap[0].G + colormap[1].G + 1) / 2); | |
| colormap[2].R = (uint8)((colormap[0].R + colormap[1].R + 1) / 2); | |
| colormap[2].A = 255u; | |
| colormap[3].B = 0u; | |
| colormap[3].G = 0u; | |
| colormap[3].R = 0u; | |
| colormap[3].A = 0u; | |
| } | |
| uint8 indices0 = data[4]; | |
| uint8 indices1 = data[5]; | |
| uint8 indices2 = data[6]; | |
| uint8 indices3 = data[7]; | |
| TRGB32 *dst_line0 = (TRGB32*)(dst_argb); | |
| TRGB32 *dst_line1 = (TRGB32*)(dst_argb + dst_pitch); | |
| TRGB32 *dst_line2 = (TRGB32*)(dst_argb + dst_pitch * 2); | |
| TRGB32 *dst_line3 = (TRGB32*)(dst_argb + dst_pitch * 3); | |
| dst_line0[0] = colormap[indices0 & 0x03]; | |
| dst_line0[1] = colormap[(indices0 & 0x0c) >> 2]; | |
| dst_line0[2] = colormap[(indices0 & 0x30) >> 4]; | |
| dst_line0[3] = colormap[indices0 >> 6]; | |
| dst_line1[0] = colormap[indices1 & 0x03]; | |
| dst_line1[1] = colormap[(indices1 & 0x0c) >> 2]; | |
| dst_line1[2] = colormap[(indices1 & 0x30) >> 4]; | |
| dst_line1[3] = colormap[indices1 >> 6]; | |
| dst_line2[0] = colormap[indices2 & 0x03]; | |
| dst_line2[1] = colormap[(indices2 & 0x0c) >> 2]; | |
| dst_line2[2] = colormap[(indices2 & 0x30) >> 4]; | |
| dst_line2[3] = colormap[indices2 >> 6]; | |
| dst_line3[0] = colormap[indices3 & 0x03]; | |
| dst_line3[1] = colormap[(indices3 & 0x0c) >> 2]; | |
| dst_line3[2] = colormap[(indices3 & 0x30) >> 4]; | |
| dst_line3[3] = colormap[indices3 >> 6]; | |
| data += 8; | |
| dst_argb += 16; | |
| } | |
| } | |
| // DXT3 info : https://en.wikipedia.org/wiki/S3_Texture_Compression#DXT2_and_DXT3 | |
| void ____DXT3ToARGBRow_C(const uint8* data, uint8* dst_argb, int width) { | |
| int dst_pitch = *(int*)dst_argb; // dirty hack to avoid another argument | |
| int x; | |
| for (x = 0; x < width; x += 4) { | |
| // Read 16 pixels of 4-bit alpha channel data | |
| uint8 alpha0 = data[0]; | |
| uint8 alpha1 = data[1]; | |
| uint8 alpha2 = data[2]; | |
| uint8 alpha3 = data[3]; | |
| uint8 alpha4 = data[4]; | |
| uint8 alpha5 = data[5]; | |
| uint8 alpha6 = data[6]; | |
| uint8 alpha7 = data[7]; | |
| // Read two 16-bit pixels | |
| uint16 color_0 = data[8] | (data[9] << 8); | |
| uint16 color_1 = data[10] | (data[11] << 8); | |
| // Read 5+6+5 bit color channels | |
| uint8 b0 = color_0 & 0x1f; | |
| uint8 g0 = (color_0 >> 5) & 0x3f; | |
| uint8 r0 = color_0 >> 11; | |
| uint8 b1 = color_1 & 0x1f; | |
| uint8 g1 = (color_1 >> 5) & 0x3f; | |
| uint8 r1 = color_1 >> 11; | |
| // Build first half of RGB32 color map (converting 5+6+5 to 8+8+8): | |
| TRGB32 colormap[4]; | |
| colormap[0].B = (b0 << 3) | (b0 >> 2); | |
| colormap[0].G = (g0 << 2) | (g0 >> 4); | |
| colormap[0].R = (r0 << 3) | (r0 >> 2); | |
| colormap[1].B = (b1 << 3) | (b1 >> 2); | |
| colormap[1].G = (g1 << 2) | (g1 >> 4); | |
| colormap[1].R = (r1 << 3) | (r1 >> 2); | |
| // Build second half of RGB32 color map : | |
| // Make up new color : 2/3 A + 1/3 B : | |
| colormap[2].B = (uint8)((2 * colormap[0].B + 1 * colormap[1].B + 2) / 3); | |
| colormap[2].G = (uint8)((2 * colormap[0].G + 1 * colormap[1].G + 2) / 3); | |
| colormap[2].R = (uint8)((2 * colormap[0].R + 1 * colormap[1].R + 2) / 3); | |
| // Make up new color : 1/3 A + 2/3 B : | |
| colormap[3].B = (uint8)((1 * colormap[0].B + 2 * colormap[1].B + 2) / 3); | |
| colormap[3].G = (uint8)((1 * colormap[0].G + 2 * colormap[1].G + 2) / 3); | |
| colormap[3].R = (uint8)((1 * colormap[0].R + 2 * colormap[1].R + 2) / 3); | |
| // Read 4 bytes worth of 2-bit color indices for 16 pixels | |
| uint8 colori0 = data[12]; | |
| uint8 colori1 = data[13]; | |
| uint8 colori2 = data[14]; | |
| uint8 colori3 = data[15]; | |
| TRGB32 *dst_line0 = (TRGB32*)(dst_argb); | |
| TRGB32 *dst_line1 = (TRGB32*)(dst_argb + dst_pitch); | |
| TRGB32 *dst_line2 = (TRGB32*)(dst_argb + dst_pitch * 2); | |
| TRGB32 *dst_line3 = (TRGB32*)(dst_argb + dst_pitch * 3); | |
| dst_line0[0] = colormap[colori0 & 0x03]; | |
| dst_line0[0].A = (alpha0 & 0x0f) | (alpha0 << 4); | |
| dst_line0[1] = colormap[(colori0 & 0x0c) >> 2]; | |
| dst_line0[1].A = (alpha0 & 0xf0) | (alpha0 >> 4); | |
| dst_line0[2] = colormap[(colori0 & 0x30) >> 4]; | |
| dst_line0[2].A = (alpha1 & 0x0f) | (alpha1 << 4); | |
| dst_line0[3] = colormap[colori0 >> 6]; | |
| dst_line0[3].A = (alpha1 & 0xf0) | (alpha1 >> 4); | |
| dst_line1[0] = colormap[colori1 & 0x03]; | |
| dst_line1[0].A = (alpha2 & 0x0f) | (alpha2 << 4); | |
| dst_line1[1] = colormap[(colori1 & 0x0c) >> 2]; | |
| dst_line1[1].A = (alpha2 & 0xf0) | (alpha2 >> 4); | |
| dst_line1[2] = colormap[(colori1 & 0x30) >> 4]; | |
| dst_line1[2].A = (alpha3 & 0x0f) | (alpha3 << 4); | |
| dst_line1[3] = colormap[colori1 >> 6]; | |
| dst_line1[3].A = (alpha3 & 0xf0) | (alpha3 >> 4); | |
| dst_line2[0] = colormap[colori2 & 0x03]; | |
| dst_line2[0].A = (alpha4 & 0x0f) | (alpha4 << 4); | |
| dst_line2[1] = colormap[(colori2 & 0x0c) >> 2]; | |
| dst_line2[1].A = (alpha4 & 0xf0) | (alpha4 >> 4); | |
| dst_line2[2] = colormap[(colori2 & 0x30) >> 4]; | |
| dst_line2[2].A = (alpha5 & 0x0f) | (alpha5 << 4); | |
| dst_line2[3] = colormap[colori2 >> 6]; | |
| dst_line2[3].A = (alpha5 & 0xf0) | (alpha5 >> 4); | |
| dst_line3[0] = colormap[colori3 & 0x03]; | |
| dst_line3[0].A = (alpha6 & 0x0f) | (alpha6 << 4); | |
| dst_line3[1] = colormap[(colori3 & 0x0c) >> 2]; | |
| dst_line3[1].A = (alpha6 & 0xf0) | (alpha6 >> 4); | |
| dst_line3[2] = colormap[(colori3 & 0x30) >> 4]; | |
| dst_line3[2].A = (alpha7 & 0x0f) | (alpha7 << 4); | |
| dst_line3[3] = colormap[colori3 >> 6]; | |
| dst_line3[3].A = (alpha7 & 0xf0) | (alpha7 >> 4); | |
| data += 16; | |
| dst_argb += 16; | |
| } | |
| } | |
| // DXT5 info : http://www.matejtomcik.com/Public/KnowHow/DXTDecompression/ | |
| void ____DXT5ToARGBRow_C(const uint8* data, uint8* dst_argb, int width) { | |
| int dst_pitch = *(int*)dst_argb; // dirty hack to avoid another argument | |
| int x; | |
| for (x = 0; x < width; x += 4) { | |
| // Read two 8-bit alphas | |
| uint8 alphamap[8]; | |
| alphamap[0] = data[0]; | |
| alphamap[1] = data[1]; | |
| // Build rest of alpha map | |
| if (alphamap[0] > alphamap[1]) { | |
| alphamap[2] = (6 * alphamap[0] + 1 * alphamap[1] + 6) / 7; | |
| alphamap[3] = (5 * alphamap[0] + 2 * alphamap[1] + 6) / 7; | |
| alphamap[4] = (4 * alphamap[0] + 3 * alphamap[1] + 6) / 7; | |
| alphamap[5] = (3 * alphamap[0] + 4 * alphamap[1] + 6) / 7; | |
| alphamap[6] = (2 * alphamap[0] + 5 * alphamap[1] + 6) / 7; | |
| alphamap[7] = (1 * alphamap[0] + 6 * alphamap[1] + 6) / 7; | |
| } | |
| else { | |
| alphamap[2] = (4 * alphamap[0] + 1 * alphamap[1] + 4) / 5; | |
| alphamap[3] = (3 * alphamap[0] + 2 * alphamap[1] + 4) / 5; | |
| alphamap[4] = (2 * alphamap[0] + 3 * alphamap[1] + 4) / 5; | |
| alphamap[5] = (1 * alphamap[0] + 4 * alphamap[1] + 4) / 5; | |
| alphamap[6] = 0u; | |
| alphamap[7] = 255u; | |
| } | |
| // Read 6 bytes worth of 3-bit alpha channal indices for 16 pixels | |
| uint8 alphai0 = data[2]; | |
| uint8 alphai1 = data[3]; | |
| uint8 alphai2 = data[4]; | |
| uint8 alphai3 = data[5]; | |
| uint8 alphai4 = data[6]; | |
| uint8 alphai5 = data[7]; | |
| // Read two 16-bit colors | |
| uint16 color_0 = data[8] | (data[9] << 8); | |
| uint16 color_1 = data[10] | (data[11] << 8); | |
| // Read 5+6+5 bit color channels | |
| uint8 b0 = color_0 & 0x1f; | |
| uint8 g0 = (color_0 >> 5) & 0x3f; | |
| uint8 r0 = color_0 >> 11; | |
| uint8 b1 = color_1 & 0x1f; | |
| uint8 g1 = (color_1 >> 5) & 0x3f; | |
| uint8 r1 = color_1 >> 11; | |
| // Build first half of RGB32 color map (converting 5+6+5 to 8+8+8): | |
| TRGB32 colormap[4]; | |
| colormap[0].B = (b0 << 3) | (b0 >> 2); | |
| colormap[0].G = (g0 << 2) | (g0 >> 4); | |
| colormap[0].R = (r0 << 3) | (r0 >> 2); | |
| colormap[1].B = (b1 << 3) | (b1 >> 2); | |
| colormap[1].G = (g1 << 2) | (g1 >> 4); | |
| colormap[1].R = (r1 << 3) | (r1 >> 2); | |
| // Build second half of RGB32 color map : | |
| // Make up new color : 2/3 A + 1/3 B : | |
| colormap[2].B = (uint8)((2 * colormap[0].B + 1 * colormap[1].B + 2) / 3); | |
| colormap[2].G = (uint8)((2 * colormap[0].G + 1 * colormap[1].G + 2) / 3); | |
| colormap[2].R = (uint8)((2 * colormap[0].R + 1 * colormap[1].R + 2) / 3); | |
| // Make up new color : 1/3 A + 2/3 B : | |
| colormap[3].B = (uint8)((1 * colormap[0].B + 2 * colormap[1].B + 2) / 3); | |
| colormap[3].G = (uint8)((1 * colormap[0].G + 2 * colormap[1].G + 2) / 3); | |
| colormap[3].R = (uint8)((1 * colormap[0].R + 2 * colormap[1].R + 2) / 3); | |
| // Read 4 bytes worth of 2-bit color indices for 16 pixels | |
| uint8 colori0 = data[12]; | |
| uint8 colori1 = data[13]; | |
| uint8 colori2 = data[14]; | |
| uint8 colori3 = data[15]; | |
| TRGB32 *dst_line0 = (TRGB32*)(dst_argb); | |
| TRGB32 *dst_line1 = (TRGB32*)(dst_argb + dst_pitch); | |
| TRGB32 *dst_line2 = (TRGB32*)(dst_argb + dst_pitch * 2); | |
| TRGB32 *dst_line3 = (TRGB32*)(dst_argb + dst_pitch * 3); | |
| dst_line0[0] = colormap[colori0 & 0x03]; | |
| dst_line0[0].A = alphamap[alphai0 & 0x07]; | |
| dst_line0[1] = colormap[(colori0 & 0x0c) >> 2]; | |
| dst_line0[1].A = alphamap[(alphai0 & 0x38 >> 3)]; | |
| dst_line0[2] = colormap[(colori0 & 0x30) >> 4]; | |
| dst_line0[2].A = alphamap[((alphai0 & 0xc0) >> 6) | (alphai1 & 0x01)]; | |
| dst_line0[3] = colormap[colori0 >> 6]; | |
| dst_line0[3].A = alphamap[(alphai1 & 0x0e) >> 1]; | |
| dst_line1[0] = colormap[colori1 & 0x03]; | |
| dst_line1[0].A = alphamap[(alphai1 & 0x70) >> 4]; | |
| dst_line1[1] = colormap[(colori1 & 0x0c) >> 2]; | |
| dst_line1[1].A = alphamap[((alphai1 & 0x80) >> 7) | ((alphai2 & 0x03) << 1)]; | |
| dst_line1[2] = colormap[(colori1 & 0x30) >> 4]; | |
| dst_line1[2].A = alphamap[(alphai2 & 0x1c) >> 2]; | |
| dst_line1[3] = colormap[colori1 >> 6]; | |
| dst_line1[3].A = alphamap[(alphai2 & 0xe0) >> 5]; | |
| dst_line2[0] = colormap[colori2 & 0x03]; | |
| dst_line2[0].A = alphamap[alphai3 & 0x07]; | |
| dst_line2[1] = colormap[(colori2 & 0x0c) >> 2]; | |
| dst_line2[1].A = alphamap[(alphai3 & 0x38 >> 3)]; | |
| dst_line2[2] = colormap[(colori2 & 0x30) >> 4]; | |
| dst_line2[2].A = alphamap[((alphai3 & 0xc0) >> 6) | (alphai4 & 0x01)]; | |
| dst_line2[3] = colormap[colori2 >> 6]; | |
| dst_line2[3].A = alphamap[(alphai4 & 0x0e) >> 1]; | |
| dst_line3[0] = colormap[colori3 & 0x03]; | |
| dst_line3[0].A = alphamap[(alphai4 & 0x70) >> 4]; | |
| dst_line3[1] = colormap[(colori3 & 0x0c) >> 2]; | |
| dst_line3[1].A = alphamap[((alphai4 & 0x80) >> 7) | ((alphai5 & 0x03) << 1)]; | |
| dst_line3[2] = colormap[(colori3 & 0x30) >> 4]; | |
| dst_line3[2].A = alphamap[(alphai5 & 0x1c) >> 2]; | |
| dst_line3[3] = colormap[colori3 >> 6]; | |
| dst_line3[3].A = alphamap[(alphai5 & 0xe0) >> 5]; | |
| data += 16; | |
| dst_argb += 16; | |
| } | |
| } | |
| void ______P8ToARGBRow_C(const uint8* src_p8, uint8* dst_argb, int width) { | |
| TRGB32 *pTexturePalette = *(TRGB32 **)dst_argb; // dirty hack to avoid another argument | |
| int x; | |
| for (x = 0; x < width; ++x) { | |
| uint8 p = src_p8[x]; | |
| TRGB32 color = pTexturePalette[p]; | |
| ((TRGB32 *)dst_argb)[x] = color; | |
| } | |
| } | |
| static __inline int32 clamp0(int32 v) { | |
| return ((-(v) >> 31) & (v)); | |
| } | |
| static __inline int32 clamp255(int32 v) { | |
| return (((255 - (v)) >> 31) | (v)) & 255; | |
| } | |
| static __inline uint32 Clamp(int32 val) { | |
| int v = clamp0(val); | |
| return (uint32)(clamp255(v)); | |
| } | |
| #if defined(_MSC_VER) && !defined(__CLR_VER) | |
| #define SIMD_ALIGNED(var) __declspec(align(16)) var | |
| #define SIMD_ALIGNED32(var) __declspec(align(64)) var | |
| typedef __declspec(align(32)) int16 lvec16[16]; | |
| typedef __declspec(align(32)) int8 lvec8[32]; | |
| #endif | |
| struct YuvConstants { | |
| lvec8 kUVToB; | |
| lvec8 kUVToG; | |
| lvec8 kUVToR; | |
| lvec16 kUVBiasB; | |
| lvec16 kUVBiasG; | |
| lvec16 kUVBiasR; | |
| lvec16 kYToRgb; | |
| }; | |
| // BT.601 YUV to RGB reference | |
| // R = (Y - 16) * 1.164 - V * -1.596 | |
| // G = (Y - 16) * 1.164 - U * 0.391 - V * 0.813 | |
| // B = (Y - 16) * 1.164 - U * -2.018 | |
| // Y contribution to R,G,B. Scale and bias. | |
| #define YG 18997 /* round(1.164 * 64 * 256 * 256 / 257) */ | |
| #define YGB -1160 /* 1.164 * 64 * -16 + 64 / 2 */ | |
| // U and V contributions to R,G,B. | |
| #define UB -128 /* max(-128, round(-2.018 * 64)) */ | |
| #define UG 25 /* round(0.391 * 64) */ | |
| #define VG 52 /* round(0.813 * 64) */ | |
| #define VR -102 /* round(-1.596 * 64) */ | |
| // Bias values to subtract 16 from Y and 128 from U and V. | |
| #define BB (UB * 128 + YGB) | |
| #define BG (UG * 128 + VG * 128 + YGB) | |
| #define BR (VR * 128 + YGB) | |
| // BT.601 constants for YUV to RGB. | |
| const YuvConstants SIMD_ALIGNED(kYuvIConstants) = { | |
| { UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, | |
| UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0, UB, 0 }, | |
| { UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, | |
| UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG, UG, VG }, | |
| { 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, | |
| 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR, 0, VR }, | |
| { BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB, BB }, | |
| { BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG, BG }, | |
| { BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR, BR }, | |
| { YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG, YG } | |
| }; | |
| // C reference code that mimics the YUV assembly. | |
| static __inline void YuvPixel(uint8 y, uint8 u, uint8 v, | |
| uint8* b, uint8* g, uint8* r, | |
| const struct YuvConstants* yuvconstants) { | |
| int ub = yuvconstants->kUVToB[0]; | |
| int ug = yuvconstants->kUVToG[0]; | |
| int vg = yuvconstants->kUVToG[1]; | |
| int vr = yuvconstants->kUVToR[1]; | |
| int bb = yuvconstants->kUVBiasB[0]; | |
| int bg = yuvconstants->kUVBiasG[0]; | |
| int br = yuvconstants->kUVBiasR[0]; | |
| int yg = yuvconstants->kYToRgb[0]; | |
| uint32 y1 = (uint32)(y * 0x0101 * yg) >> 16; | |
| *b = Clamp((int32)(-(u * ub) + y1 + bb) >> 6); | |
| *g = Clamp((int32)(-(u * ug + v * vg) + y1 + bg) >> 6); | |
| *r = Clamp((int32)(-(v * vr) + y1 + br) >> 6); | |
| } | |
| void ____YUY2ToARGBRow_C(const uint8* src_yuy2, | |
| uint8* rgb_buf, | |
| int width) { | |
| const struct YuvConstants* yuvconstants = &kYuvIConstants; // hack to avoid another argument | |
| int x; | |
| for (x = 0; x < width - 1; x += 2) { | |
| YuvPixel(src_yuy2[0], src_yuy2[1], src_yuy2[3], | |
| rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); | |
| rgb_buf[3] = 255; | |
| YuvPixel(src_yuy2[2], src_yuy2[1], src_yuy2[3], | |
| rgb_buf + 4, rgb_buf + 5, rgb_buf + 6, yuvconstants); | |
| rgb_buf[7] = 255; | |
| src_yuy2 += 4; | |
| rgb_buf += 8; // Advance 2 pixels. | |
| } | |
| if (width & 1) { | |
| YuvPixel(src_yuy2[0], src_yuy2[1], src_yuy2[3], | |
| rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); | |
| rgb_buf[3] = 255; | |
| } | |
| } | |
| void ____UYVYToARGBRow_C(const uint8* src_uyvy, | |
| uint8* rgb_buf, | |
| int width) { | |
| const struct YuvConstants* yuvconstants = &kYuvIConstants; // hack to avoid another argument | |
| int x; | |
| for (x = 0; x < width - 1; x += 2) { | |
| YuvPixel(src_uyvy[1], src_uyvy[0], src_uyvy[2], | |
| rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); | |
| rgb_buf[3] = 255; | |
| YuvPixel(src_uyvy[3], src_uyvy[0], src_uyvy[2], | |
| rgb_buf + 4, rgb_buf + 5, rgb_buf + 6, yuvconstants); | |
| rgb_buf[7] = 255; | |
| src_uyvy += 4; | |
| rgb_buf += 8; // Advance 2 pixels. | |
| } | |
| if (width & 1) { | |
| YuvPixel(src_uyvy[1], src_uyvy[0], src_uyvy[2], | |
| rgb_buf + 0, rgb_buf + 1, rgb_buf + 2, yuvconstants); | |
| rgb_buf[3] = 255; | |
| } | |
| } | |
| static const XTL::FormatToARGBRow ComponentConverters[] = { | |
| nullptr, // NoCmpnts, | |
| ARGB1555ToARGBRow_C, // A1R5G5B5, | |
| X1R5G5B5ToARGBRow_C, // X1R5G5B5, // Test : Convert X into 255 | |
| ARGB4444ToARGBRow_C, // A4R4G4B4, | |
| RGB565ToARGBRow_C, // __R5G6B5, // NOTE : A=255 | |
| A8R8G8B8ToARGBRow_C, // A8R8G8B8, | |
| X8R8G8B8ToARGBRow_C, // X8R8G8B8, // Test : Convert X into 255 | |
| ____R8B8ToARGBRow_C, // ____R8B8, // NOTE : A takes R, G takes B | |
| ____G8B8ToARGBRow_C, // ____G8B8, // NOTE : A takes G, R takes B | |
| ______A8ToARGBRow_C, // ______A8, | |
| __R6G5B5ToARGBRow_C, // __R6G5B5, | |
| R5G5B5A1ToARGBRow_C, // R5G5B5A1, | |
| R4G4B4A4ToARGBRow_C, // R4G4B4A4, | |
| A8B8G8R8ToARGBRow_C, // A8B8G8R8, | |
| B8G8R8A8ToARGBRow_C, // B8G8R8A8, | |
| R8G8B8A8ToARGBRow_C, // R8G8B8A8, | |
| ______L8ToARGBRow_C, // ______L8, // NOTE : A=255, R=G=B= L | |
| _____AL8ToARGBRow_C, // _____AL8, // NOTE : A=R=G=B= L | |
| _____L16ToARGBRow_C, // _____L16, // NOTE : Actually G8B8, with A=R=255 | |
| ____A8L8ToARGBRow_C, // ____A8L8, // NOTE : R=G=B= L | |
| ____DXT1ToARGBRow_C, // ____DXT1 | |
| ____DXT3ToARGBRow_C, // ____DXT3 | |
| ____DXT5ToARGBRow_C, // ____DXT5 | |
| ______P8ToARGBRow_C, // ______P8 | |
| ____YUY2ToARGBRow_C, // ____YUY2 | |
| ____UYVYToARGBRow_C, // ____UYVY | |
| }; | |
| enum _FormatStorage { | |
| Undfnd = 0, // Undefined | |
| Linear, | |
| Swzzld, // Swizzled | |
| Cmprsd // Compressed | |
| }; | |
| enum _FormatUsage { | |
| Texture = 0, | |
| RenderTarget, | |
| DepthBuffer | |
| }; | |
| typedef struct _FormatInfo { | |
| uint8_t bits_per_pixel; | |
| _FormatStorage stored; | |
| _ComponentEncoding components; | |
| XTL::D3DFORMAT pc; | |
| _FormatUsage usage; | |
| char *warning; | |
| } FormatInfo; | |
| static const FormatInfo FormatInfos[] = { | |
| // Notes : | |
| // * This table should use a native format that most closely mirrors the Xbox format, | |
| // and (for now) MUST use a format that uses the same number of bits/bytes per pixel, | |
| // as otherwise locked buffers wouldn't be of the same size as on the Xbox, which | |
| // could lead to out-of-bounds access violations. | |
| // * Each format for which the host D3D8 doesn't have an identical native format, | |
| // and does specify color components (other than NoCmpnts), MUST specify this fact | |
| // in the warning field, so EmuXBFormatRequiresConversionToARGB can return a conversion | |
| // to ARGB is needed (which is implemented in EMUPATCH(D3DResource_Register). | |
| /* 0x00 X_D3DFMT_L8 */ { 8, Swzzld, ______L8, XTL::D3DFMT_L8 }, | |
| /* 0x01 X_D3DFMT_AL8 */ { 8, Swzzld, _____AL8, XTL::D3DFMT_L8 , Texture, "X_D3DFMT_AL8 -> D3DFMT_L8" }, | |
| /* 0x02 X_D3DFMT_A1R5G5B5 */ { 16, Swzzld, A1R5G5B5, XTL::D3DFMT_A1R5G5B5 }, | |
| /* 0x03 X_D3DFMT_X1R5G5B5 */ { 16, Swzzld, X1R5G5B5, XTL::D3DFMT_X1R5G5B5 , RenderTarget }, | |
| /* 0x04 X_D3DFMT_A4R4G4B4 */ { 16, Swzzld, A4R4G4B4, XTL::D3DFMT_A4R4G4B4 }, | |
| /* 0x05 X_D3DFMT_R5G6B5 */ { 16, Swzzld, __R5G6B5, XTL::D3DFMT_R5G6B5 , RenderTarget }, | |
| /* 0x06 X_D3DFMT_A8R8G8B8 */ { 32, Swzzld, A8R8G8B8, XTL::D3DFMT_A8R8G8B8 , RenderTarget }, | |
| /* 0x07 X_D3DFMT_X8R8G8B8 */ { 32, Swzzld, X8R8G8B8, XTL::D3DFMT_X8R8G8B8 , RenderTarget }, // Alias : X_D3DFMT_X8L8V8U8 | |
| /* 0x08 undefined */ {}, | |
| /* 0x09 undefined */ {}, | |
| /* 0x0A undefined */ {}, | |
| /* 0x0B X_D3DFMT_P8 */ { 8, Swzzld, ______P8, XTL::D3DFMT_P8 , Texture, "X_D3DFMT_P8 -> D3DFMT_L8" }, // 8-bit palletized | |
| /* 0x0C X_D3DFMT_DXT1 */ { 4, Cmprsd, ____DXT1, XTL::D3DFMT_DXT1 }, // opaque/one-bit alpha // NOTE : DXT1 is half byte per pixel, so divide Size and Pitch calculations by two! | |
| /* 0x0D undefined */ {}, | |
| /* 0x0E X_D3DFMT_DXT3 */ { 8, Cmprsd, ____DXT3, XTL::D3DFMT_DXT3 }, // Alias : X_D3DFMT_DXT2 // linear alpha | |
| /* 0x0F X_D3DFMT_DXT5 */ { 8, Cmprsd, ____DXT5, XTL::D3DFMT_DXT5 }, // Alias : X_D3DFMT_DXT4 // interpolated alpha | |
| /* 0x10 X_D3DFMT_LIN_A1R5G5B5 */ { 16, Linear, A1R5G5B5, XTL::D3DFMT_A1R5G5B5 }, | |
| /* 0x11 X_D3DFMT_LIN_R5G6B5 */ { 16, Linear, __R5G6B5, XTL::D3DFMT_R5G6B5 , RenderTarget }, | |
| /* 0x12 X_D3DFMT_LIN_A8R8G8B8 */ { 32, Linear, A8R8G8B8, XTL::D3DFMT_A8R8G8B8 , RenderTarget }, | |
| /* 0x13 X_D3DFMT_LIN_L8 */ { 8, Linear, ______L8, XTL::D3DFMT_L8 , RenderTarget }, | |
| /* 0x14 undefined */ {}, | |
| /* 0x15 undefined */ {}, | |
| /* 0x16 X_D3DFMT_LIN_R8B8 */ { 16, Linear, ____R8B8, XTL::D3DFMT_R5G6B5 , Texture, "X_D3DFMT_LIN_R8B8 -> D3DFMT_R5G6B5" }, | |
| /* 0x17 X_D3DFMT_LIN_G8B8 */ { 16, Linear, ____G8B8, XTL::D3DFMT_R5G6B5 , RenderTarget, "X_D3DFMT_LIN_G8B8 -> D3DFMT_R5G6B5" }, // Alias : X_D3DFMT_LIN_V8U8 | |
| /* 0x18 undefined */ {}, | |
| /* 0x19 X_D3DFMT_A8 */ { 8, Swzzld, ______A8, XTL::D3DFMT_A8 }, | |
| /* 0x1A X_D3DFMT_A8L8 */ { 16, Swzzld, ____A8L8, XTL::D3DFMT_A8L8 }, | |
| /* 0x1B X_D3DFMT_LIN_AL8 */ { 8, Linear, _____AL8, XTL::D3DFMT_L8 , Texture, "X_D3DFMT_LIN_AL8 -> D3DFMT_L8" }, | |
| /* 0x1C X_D3DFMT_LIN_X1R5G5B5 */ { 16, Linear, X1R5G5B5, XTL::D3DFMT_X1R5G5B5 , RenderTarget }, | |
| /* 0x1D X_D3DFMT_LIN_A4R4G4B4 */ { 16, Linear, A4R4G4B4, XTL::D3DFMT_A4R4G4B4 }, | |
| /* 0x1E X_D3DFMT_LIN_X8R8G8B8 */ { 32, Linear, X8R8G8B8, XTL::D3DFMT_X8R8G8B8 , RenderTarget }, // Alias : X_D3DFMT_LIN_X8L8V8U8 | |
| /* 0x1F X_D3DFMT_LIN_A8 */ { 8, Linear, ______A8, XTL::D3DFMT_A8 }, | |
| /* 0x20 X_D3DFMT_LIN_A8L8 */ { 16, Linear, ____A8L8, XTL::D3DFMT_A8L8 }, | |
| /* 0x21 undefined */ {}, | |
| /* 0x22 undefined */ {}, | |
| /* 0x23 undefined */ {}, | |
| /* 0x24 X_D3DFMT_YUY2 */ { 16, Linear, ____YUY2, XTL::D3DFMT_YUY2 }, | |
| /* 0x25 X_D3DFMT_UYVY */ { 16, Linear, ____UYVY, XTL::D3DFMT_UYVY }, | |
| /* 0x26 undefined */ {}, | |
| /* 0x27 X_D3DFMT_L6V5U5 */ { 16, Swzzld, __R6G5B5, XTL::D3DFMT_L6V5U5 }, // Alias : X_D3DFMT_R6G5B5 // XQEMU NOTE : This might be signed | |
| /* 0x28 X_D3DFMT_V8U8 */ { 16, Swzzld, ____G8B8, XTL::D3DFMT_V8U8 }, // Alias : X_D3DFMT_G8B8 // XQEMU NOTE : This might be signed | |
| /* 0x29 X_D3DFMT_R8B8 */ { 16, Swzzld, ____R8B8, XTL::D3DFMT_R5G6B5 , Texture, "X_D3DFMT_R8B8 -> D3DFMT_R5G6B5" }, // XQEMU NOTE : This might be signed | |
| /* 0x2A X_D3DFMT_D24S8 */ { 32, Swzzld, NoCmpnts, XTL::D3DFMT_D24S8 , DepthBuffer }, | |
| /* 0x2B X_D3DFMT_F24S8 */ { 32, Swzzld, NoCmpnts, XTL::D3DFMT_D24S8 , DepthBuffer, "X_D3DFMT_F24S8 -> D3DFMT_D24S8" }, // HACK : PC doesn't have D3DFMT_F24S8 (Float vs Int) | |
| /* 0x2C X_D3DFMT_D16 */ { 16, Swzzld, NoCmpnts, XTL::D3DFMT_D16_LOCKABLE, DepthBuffer }, // Alias : X_D3DFMT_D16_LOCKABLE // Note : D3DFMT_D16 is always lockable on Xbox, D3DFMT_D16 on host is not. | |
| /* 0x2D X_D3DFMT_F16 */ { 16, Swzzld, NoCmpnts, XTL::D3DFMT_D16_LOCKABLE, DepthBuffer, "X_D3DFMT_F16 -> D3DFMT_D16" }, // HACK : PC doesn't have D3DFMT_F16 (Float vs Int) | |
| /* 0x2E X_D3DFMT_LIN_D24S8 */ { 32, Linear, NoCmpnts, XTL::D3DFMT_D24S8 , DepthBuffer }, | |
| /* 0x2F X_D3DFMT_LIN_F24S8 */ { 32, Linear, NoCmpnts, XTL::D3DFMT_D24S8 , DepthBuffer, "X_D3DFMT_LIN_F24S8 -> D3DFMT_D24S8" }, // HACK : PC doesn't have D3DFMT_F24S8 (Float vs Int) | |
| /* 0x30 X_D3DFMT_LIN_D16 */ { 16, Linear, NoCmpnts, XTL::D3DFMT_D16_LOCKABLE, DepthBuffer }, // Note : D3DFMT_D16 is always lockable on Xbox, D3DFMT_D16 on host is not. | |
| /* 0x31 X_D3DFMT_LIN_F16 */ { 16, Linear, NoCmpnts, XTL::D3DFMT_D16_LOCKABLE, DepthBuffer, "X_D3DFMT_LIN_F16 -> D3DFMT_D16" }, // HACK : PC doesn't have D3DFMT_F16 (Float vs Int) | |
| /* 0x32 X_D3DFMT_L16 */ { 16, Swzzld, _____L16, XTL::D3DFMT_A8L8 , Texture, "X_D3DFMT_L16 -> D3DFMT_A8L8" }, | |
| /* 0x33 X_D3DFMT_V16U16 */ { 32, Swzzld, NoCmpnts, XTL::D3DFMT_V16U16 }, | |
| /* 0x34 undefined */ {}, | |
| /* 0x35 X_D3DFMT_LIN_L16 */ { 16, Linear, _____L16, XTL::D3DFMT_A8L8 , Texture, "X_D3DFMT_LIN_L16 -> D3DFMT_A8L8" }, | |
| /* 0x36 X_D3DFMT_LIN_V16U16 */ { 32, Linear, NoCmpnts, XTL::D3DFMT_V16U16 }, // Note : Seems ununsed on Xbox | |
| /* 0x37 X_D3DFMT_LIN_L6V5U5 */ { 16, Linear, __R6G5B5, XTL::D3DFMT_L6V5U5 }, // Alias : X_D3DFMT_LIN_R6G5B5 | |
| /* 0x38 X_D3DFMT_R5G5B5A1 */ { 16, Swzzld, R5G5B5A1, XTL::D3DFMT_A1R5G5B5 , Texture, "X_D3DFMT_R5G5B5A1 -> D3DFMT_A1R5G5B5" }, | |
| /* 0x39 X_D3DFMT_R4G4B4A4 */ { 16, Swzzld, R4G4B4A4, XTL::D3DFMT_A4R4G4B4 , Texture, "X_D3DFMT_R4G4B4A4 -> D3DFMT_A4R4G4B4" }, | |
| /* 0x3A X_D3DFMT_Q8W8V8U8 */ { 32, Swzzld, A8B8G8R8, XTL::D3DFMT_Q8W8V8U8 }, // Alias : X_D3DFMT_A8B8G8R8 // TODO : Needs testcase. | |
| /* 0x3B X_D3DFMT_B8G8R8A8 */ { 32, Swzzld, B8G8R8A8, XTL::D3DFMT_A8R8G8B8 , Texture, "X_D3DFMT_B8G8R8A8 -> D3DFMT_A8R8G8B8" }, | |
| /* 0x3C X_D3DFMT_R8G8B8A8 */ { 32, Swzzld, R8G8B8A8, XTL::D3DFMT_A8R8G8B8 , Texture, "X_D3DFMT_R8G8B8A8 -> D3DFMT_A8R8G8B8" }, | |
| /* 0x3D X_D3DFMT_LIN_R5G5B5A1 */ { 16, Linear, R5G5B5A1, XTL::D3DFMT_A1R5G5B5 , Texture, "X_D3DFMT_LIN_R5G5B5A1 -> D3DFMT_A1R5G5B5" }, | |
| /* 0x3E X_D3DFMT_LIN_R4G4B4A4 */ { 16, Linear, R4G4B4A4, XTL::D3DFMT_A4R4G4B4 , Texture, "X_D3DFMT_LIN_R4G4B4A4 -> D3DFMT_A4R4G4B4" }, | |
| /* 0x3F X_D3DFMT_LIN_A8B8G8R8 */ { 32, Linear, A8B8G8R8, XTL::D3DFMT_A8R8G8B8 , Texture, "X_D3DFMT_LIN_A8B8G8R8 -> D3DFMT_A8R8G8B8" }, | |
| /* 0x40 X_D3DFMT_LIN_B8G8R8A8 */ { 32, Linear, B8G8R8A8, XTL::D3DFMT_A8R8G8B8 , Texture, "X_D3DFMT_LIN_B8G8R8A8 -> D3DFMT_A8R8G8B8" }, | |
| /* 0x41 X_D3DFMT_LIN_R8G8B8A8 */ { 32, Linear, R8G8B8A8, XTL::D3DFMT_A8R8G8B8 , Texture, "X_D3DFMT_LIN_R8G8B8A8 -> D3DFMT_A8R8G8B8" }, | |
| #if 0 | |
| /* 0x42 to 0x63 undefined */ {},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{},{}, | |
| /* 0x64 X_D3DFMT_VERTEXDATA */ { 8, Linear, NoCmpnts, XTL::D3DFMT_VERTEXDATA }, | |
| /* 0x65 X_D3DFMT_INDEX16 */ { 16, Linear, NoCmpnts, XTL::D3DFMT_INDEX16 }, // Dxbx addition : X_D3DFMT_INDEX16 is not an Xbox format, but used internally | |
| #endif | |
| }; | |
| const XTL::FormatToARGBRow XTL::EmuXBFormatComponentConverter(X_D3DFORMAT Format) | |
| { | |
| if (Format <= X_D3DFMT_LIN_R8G8B8A8) | |
| if (FormatInfos[Format].components != NoCmpnts) | |
| return ComponentConverters[FormatInfos[Format].components]; | |
| return nullptr; | |
| } | |
| // Is there a converter available from the supplied format to ARGB? | |
| bool XTL::EmuXBFormatCanBeConvertedToARGB(X_D3DFORMAT Format) | |
| { | |
| const FormatToARGBRow info = EmuXBFormatComponentConverter(Format); | |
| return (info != nullptr); | |
| } | |
| // Returns if convertion to ARGB is required. This is the case when | |
| // the format has a warning message and there's a converter present. | |
| bool XTL::EmuXBFormatRequiresConversionToARGB(X_D3DFORMAT Format) | |
| { | |
| if (FormatInfos[Format].warning != nullptr) | |
| if (EmuXBFormatCanBeConvertedToARGB(Format)) | |
| return true; | |
| return false; | |
| } | |
| DWORD XTL::EmuXBFormatBitsPerPixel(X_D3DFORMAT Format) | |
| { | |
| if (Format <= X_D3DFMT_LIN_R8G8B8A8) | |
| if (FormatInfos[Format].bits_per_pixel > 0) // TODO : Remove this | |
| return FormatInfos[Format].bits_per_pixel; | |
| return 16; // TODO : 8 | |
| } | |
| DWORD XTL::EmuXBFormatBytesPerPixel(X_D3DFORMAT Format) | |
| { | |
| return ((EmuXBFormatBitsPerPixel(Format) + 4) / 8); | |
| } | |
| BOOL XTL::EmuXBFormatIsCompressed(X_D3DFORMAT Format) | |
| { | |
| if (Format <= X_D3DFMT_LIN_R8G8B8A8) | |
| return (FormatInfos[Format].stored == Cmprsd); | |
| return false; | |
| } | |
| BOOL XTL::EmuXBFormatIsLinear(X_D3DFORMAT Format) | |
| { | |
| if (Format <= X_D3DFMT_LIN_R8G8B8A8) | |
| return (FormatInfos[Format].stored == Linear); | |
| return (Format == X_D3DFMT_VERTEXDATA); // TODO : false; | |
| } | |
| BOOL XTL::EmuXBFormatIsSwizzled(X_D3DFORMAT Format) | |
| { | |
| if (Format <= X_D3DFMT_LIN_R8G8B8A8) | |
| return (FormatInfos[Format].stored == Swzzld); | |
| return false; | |
| } | |
| BOOL XTL::EmuXBFormatIsRenderTarget(X_D3DFORMAT Format) | |
| { | |
| if (Format <= X_D3DFMT_LIN_R8G8B8A8) | |
| return (FormatInfos[Format].usage == RenderTarget); | |
| return false; | |
| } | |
| BOOL XTL::EmuXBFormatIsDepthBuffer(X_D3DFORMAT Format) | |
| { | |
| if (Format <= X_D3DFMT_LIN_R8G8B8A8) | |
| return (FormatInfos[Format].usage == DepthBuffer); | |
| return false; | |
| } | |
| XTL::D3DFORMAT XTL::EmuXB2PC_D3DFormat(X_D3DFORMAT Format) | |
| { | |
| if (Format <= X_D3DFMT_LIN_R8G8B8A8 && Format != -1 /*X_D3DFMT_UNKNOWN*/) // The last bit prevents crashing (Metal Slug 3) | |
| { | |
| const FormatInfo *info = &FormatInfos[Format]; | |
| if (info->warning != nullptr) { | |
| DbgPrintf("EmuXB2PC_D3DFormat %s\n", info->warning); | |
| } | |
| return info->pc; | |
| } | |
| switch (Format) { | |
| case X_D3DFMT_VERTEXDATA: | |
| return D3DFMT_VERTEXDATA; | |
| case ((X_D3DFORMAT)0xffffffff): | |
| return D3DFMT_UNKNOWN; // TODO -oCXBX: Not sure if this counts as swizzled or not... | |
| default: | |
| CxbxKrnlCleanup("EmuXB2PC_D3DFormat: Unknown Format (0x%.08X)", Format); | |
| } | |
| return D3DFMT_UNKNOWN; | |
| } | |
| XTL::X_D3DFORMAT XTL::EmuPC2XB_D3DFormat(D3DFORMAT Format) | |
| { | |
| X_D3DFORMAT result; | |
| switch(Format) | |
| { | |
| case D3DFMT_YUY2: | |
| result = X_D3DFMT_YUY2; | |
| break; | |
| case D3DFMT_UYVY: | |
| result = X_D3DFMT_UYVY; | |
| break; | |
| case D3DFMT_R5G6B5: | |
| result = X_D3DFMT_LIN_R5G6B5; | |
| break; // Linear | |
| // Result := X_D3DFMT_R5G6B5; // Swizzled | |
| case D3DFMT_D24S8: | |
| result = X_D3DFMT_D24S8; | |
| break; // Swizzled | |
| case D3DFMT_DXT5: | |
| result = X_D3DFMT_DXT5; | |
| break; // Compressed | |
| case D3DFMT_DXT4: | |
| result = X_D3DFMT_DXT4; // Same as X_D3DFMT_DXT5 | |
| break; // Compressed | |
| case D3DFMT_DXT3: | |
| result = X_D3DFMT_DXT3; | |
| break; // Compressed | |
| case D3DFMT_DXT2: | |
| result = X_D3DFMT_DXT2; // Same as X_D3DFMT_DXT3 | |
| break; // Compressed | |
| case D3DFMT_DXT1: | |
| result = X_D3DFMT_DXT1; | |
| break; // Compressed | |
| case D3DFMT_A1R5G5B5: | |
| result = X_D3DFMT_LIN_A1R5G5B5; | |
| break; // Linear | |
| case D3DFMT_X8R8G8B8: | |
| result = X_D3DFMT_LIN_X8R8G8B8; | |
| break; // Linear | |
| // Result := X_D3DFMT_X8R8G8B8; // Swizzled | |
| case D3DFMT_A8R8G8B8: | |
| // Result := X_D3DFMT_LIN_A8R8G8B8; // Linear | |
| result = X_D3DFMT_A8R8G8B8; | |
| break; | |
| case D3DFMT_A4R4G4B4: | |
| result = X_D3DFMT_LIN_A4R4G4B4; | |
| break; // Linear | |
| // Result := X_D3DFMT_A4R4G4B4; // Swizzled | |
| case D3DFMT_X1R5G5B5: // Linear | |
| result = X_D3DFMT_LIN_X1R5G5B5; | |
| break; | |
| case D3DFMT_A8: | |
| result = X_D3DFMT_A8; | |
| break; | |
| case D3DFMT_L8: | |
| result = X_D3DFMT_LIN_L8; | |
| break; // Linear | |
| // Result := X_D3DFMT_L8; // Swizzled | |
| case D3DFMT_D16: case D3DFMT_D16_LOCKABLE: | |
| result = X_D3DFMT_D16_LOCKABLE; | |
| break; // Swizzled | |
| case D3DFMT_UNKNOWN: | |
| result = ((X_D3DFORMAT)0xffffffff); | |
| break; | |
| // Dxbx additions : | |
| case D3DFMT_L6V5U5: | |
| result = X_D3DFMT_L6V5U5; | |
| break; // Swizzled | |
| case D3DFMT_V8U8: | |
| result = X_D3DFMT_V8U8; | |
| break; // Swizzled | |
| case D3DFMT_V16U16: | |
| result = X_D3DFMT_V16U16; | |
| break; // Swizzled | |
| case D3DFMT_VERTEXDATA: | |
| result = X_D3DFMT_VERTEXDATA; | |
| break; | |
| default: | |
| CxbxKrnlCleanup("EmuPC2XB_D3DFormat: Unknown Format (%d)", Format); | |
| } | |
| return result; | |
| } | |
| DWORD XTL::EmuXB2PC_D3DLock(DWORD Flags) | |
| { | |
| DWORD NewFlags = 0; | |
| // Need to convert the flags, TODO: fix the xbox extensions | |
| // if(Flags & X_D3DLOCK_NOFLUSH) | |
| // NewFlags ^= 0; | |
| if(Flags & X_D3DLOCK_NOOVERWRITE) | |
| NewFlags |= D3DLOCK_NOOVERWRITE; | |
| // if(Flags & X_D3DLOCK_TILED) | |
| // NewFlags ^= 0; | |
| if(Flags & X_D3DLOCK_READONLY) | |
| NewFlags |= D3DLOCK_READONLY; | |
| return NewFlags; | |
| } | |
| // convert from xbox to pc multisample formats | |
| XTL::D3DMULTISAMPLE_TYPE XTL::EmuXB2PC_D3DMultiSampleFormat(DWORD Type) | |
| { | |
| D3DMULTISAMPLE_TYPE result; | |
| switch (Type & 0xFFFF) | |
| { | |
| case X_D3DMULTISAMPLE_NONE: | |
| result = D3DMULTISAMPLE_NONE; | |
| break; | |
| case X_D3DMULTISAMPLE_2_SAMPLES_MULTISAMPLE_LINEAR: | |
| case X_D3DMULTISAMPLE_2_SAMPLES_MULTISAMPLE_QUINCUNX: | |
| case X_D3DMULTISAMPLE_2_SAMPLES_SUPERSAMPLE_HORIZONTAL_LINEAR: | |
| case X_D3DMULTISAMPLE_2_SAMPLES_SUPERSAMPLE_VERTICAL_LINEAR: | |
| result = D3DMULTISAMPLE_2_SAMPLES; | |
| break; | |
| case X_D3DMULTISAMPLE_4_SAMPLES_MULTISAMPLE_LINEAR: | |
| case X_D3DMULTISAMPLE_4_SAMPLES_MULTISAMPLE_GAUSSIAN: | |
| case X_D3DMULTISAMPLE_4_SAMPLES_SUPERSAMPLE_LINEAR: | |
| case X_D3DMULTISAMPLE_4_SAMPLES_SUPERSAMPLE_GAUSSIAN: | |
| result = D3DMULTISAMPLE_4_SAMPLES; | |
| break; | |
| case X_D3DMULTISAMPLE_9_SAMPLES_MULTISAMPLE_GAUSSIAN: | |
| case X_D3DMULTISAMPLE_9_SAMPLES_SUPERSAMPLE_GAUSSIAN: | |
| result = D3DMULTISAMPLE_9_SAMPLES; | |
| break; | |
| default: | |
| EmuWarning("Unknown Multisample Type (0x%X)!\x0d\x0a.", Type); | |
| result = D3DMULTISAMPLE_NONE; | |
| } | |
| return result; | |
| } | |
| // lookup table for converting vertex count to primitive count | |
| UINT XTL::EmuD3DVertexToPrimitive[11][2] = | |
| { | |
| {0, 0}, // NULL | |
| {1, 0}, // X_D3DPT_POINTLIST | |
| {2, 0}, // X_D3DPT_LINELIST | |
| {1, 1}, // X_D3DPT_LINELOOP | |
| {1, 1}, // X_D3DPT_LINESTRIP | |
| {3, 0}, // X_D3DPT_TRIANGLELIST | |
| {1, 2}, // X_D3DPT_TRIANGLESTRIP | |
| {1, 2}, // X_D3DPT_TRIANGLEFAN | |
| {4, 0}, // X_D3DPT_QUADLIST | |
| {2, 2}, // X_D3DPT_QUADSTRIP | |
| {1, 0}, // X_D3DPT_POLYGON | |
| }; | |
| // conversion table for xbox->pc primitive types | |
| XTL::D3DPRIMITIVETYPE XTL::EmuPrimitiveTypeLookup[] = | |
| { | |
| /* NULL = 0 */ (XTL::D3DPRIMITIVETYPE)0, | |
| /* D3DPT_POINTLIST = 1, */ XTL::D3DPT_POINTLIST, | |
| /* D3DPT_LINELIST = 2, */ XTL::D3DPT_LINELIST, | |
| /* D3DPT_LINELOOP = 3, Xbox */ XTL::D3DPT_LINESTRIP, | |
| /* D3DPT_LINESTRIP = 4, */ XTL::D3DPT_LINESTRIP, | |
| /* D3DPT_TRIANGLELIST = 5, */ XTL::D3DPT_TRIANGLELIST, | |
| /* D3DPT_TRIANGLESTRIP = 6, */ XTL::D3DPT_TRIANGLESTRIP, | |
| /* D3DPT_TRIANGLEFAN = 7, */ XTL::D3DPT_TRIANGLEFAN, | |
| /* D3DPT_QUADLIST = 8, Xbox */ XTL::D3DPT_TRIANGLELIST, | |
| /* D3DPT_QUADSTRIP = 9, Xbox */ XTL::D3DPT_TRIANGLESTRIP, | |
| /* D3DPT_POLYGON = 10, Xbox */ XTL::D3DPT_TRIANGLEFAN, | |
| /* D3DPT_MAX = 11, */ (XTL::D3DPRIMITIVETYPE)11 | |
| }; | |
| // render state conversion table | |
| CONST DWORD XTL::EmuD3DRenderStateSimpleEncoded[174] = | |
| { | |
| // WARNING: This lookup table strongly binds us to an SDK with these | |
| // specific #define values for D3DRS_*. Make VERY sure that you have | |
| // the correct lookup values; | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 0 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 2 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 4 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 6 | |
| X_D3DRSSE_UNK, 0x0004037c, // 8 - , D3DRS_SHADEMODE | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 10 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 12 | |
| 0x0004035c, 0x00040300, // 14 - D3DRS_ZWRITEENABLE, D3DRS_ALPHATESTENABLE | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 16 | |
| X_D3DRSSE_UNK, 0x00040344, // 18 - , D3DRS_SRCBLEND | |
| 0x00040348, X_D3DRSSE_UNK, // 20 - D3DRS_DESTBLEND | |
| X_D3DRSSE_UNK, 0x00040354, // 22 - , D3DRS_ZFUNC | |
| 0x00040340, 0x0004033c, // 24 - D3DRS_ALPHAREF, D3DRS_ALPHAFUNC | |
| 0x00040310, 0x00040304, // 26 - D3DRS_DITHERENABLE, D3DRS_ALPHABLENDENABLE | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 28 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 30 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 32 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 34 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 36 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 38 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 40 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 42 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 44 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 46 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 48 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 50 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 52 | |
| 0x00040374, 0x00040378, // 54 - D3DRS_STENCILZFAIL, D3DRS_STENCILPASS | |
| 0x00040364, 0x00040368, // 56 - D3DRS_STENCILFUNC, D3DRS_STENCILREF | |
| 0x0004036c, 0x00040360, // 58 - D3DRS_STENCILMASK, D3DRS_STENCILWRITEMASK | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 60 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 62 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 64 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 66 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 68 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 70 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 72 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 74 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 76 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 78 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 80 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 82 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 84 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 86 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 88 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 90 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 92 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 94 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 96 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 98 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 100 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 102 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 104 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 106 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 108 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 110 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 112 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 114 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 116 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 118 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 120 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 122 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 124 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 126 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 128 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 130 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 132 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 134 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 136 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 138 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 140 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 142 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 144 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 146 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 148 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 150 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 152 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 154 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 156 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 158 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 160 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 162 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 164 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 166 | |
| 0x00040358, X_D3DRSSE_UNK, // 168 - D3DRS_COLORWRITEENABLE | |
| X_D3DRSSE_UNK, 0x00040350, // 170 | |
| X_D3DRSSE_UNK, X_D3DRSSE_UNK, // 172 | |
| }; | |
| void XTL::EmuUnswizzleBox | |
| ( | |
| CONST PVOID pSrcBuff, | |
| CONST DWORD dwWidth, | |
| CONST DWORD dwHeight, | |
| CONST DWORD dwDepth, | |
| CONST DWORD dwBytesPerPixel, | |
| CONST PVOID pDstBuff, | |
| CONST DWORD dwDstRowPitch, | |
| CONST DWORD dwDstSlicePitch | |
| ) // Source : Dxbx | |
| { | |
| DWORD dwMaskX = 0, dwMaskY = 0, dwMaskZ = 0; | |
| for (uint i=1, j=1; (i < dwWidth) || (i < dwHeight) || (i < dwDepth); i <<= 1) { | |
| if (i < dwWidth) { | |
| dwMaskX |= j; | |
| j <<= 1; | |
| } | |
| if (i < dwHeight) { | |
| dwMaskY |= j; | |
| j <<= 1; | |
| } | |
| if (i < dwDepth) { | |
| dwMaskZ |= j; | |
| j <<= 1; | |
| } | |
| } | |
| const DWORD dwStartX = 0; | |
| const DWORD dwStartY = 0; | |
| const DWORD dwStartZ = 0; | |
| DWORD dwZ = dwStartZ; | |
| switch (dwBytesPerPixel) { | |
| case 1: { | |
| const uint8_t *pSrc = (uint8_t *)pSrcBuff; | |
| uint8_t *pDestSlice = (uint8_t *)pDstBuff; | |
| for (uint z = 0; z < dwDepth; z++) { | |
| uint8_t *pDestRow = pDestSlice; | |
| DWORD dwY = dwStartY; | |
| for (uint y = 0; y < dwHeight; y++) { | |
| DWORD dwYZ = dwY | dwZ; | |
| DWORD dwX = dwStartX; | |
| for (uint x = 0; x < dwWidth; x++) { | |
| uint delta = dwX | dwYZ; | |
| pDestRow[x] = pSrc[delta]; // copy one pixel | |
| dwX = (dwX - dwMaskX) & dwMaskX; // step to next pixel in source | |
| } | |
| pDestRow += dwDstRowPitch; // / 1; // = / dwBPP; // step to next line in destination | |
| dwY = (dwY - dwMaskY) & dwMaskY; // step to next line in source | |
| } | |
| pDestSlice += dwDstSlicePitch; // / 1; // = / dwBPP; // step to next level in destination | |
| dwZ = (dwZ - dwMaskZ) & dwMaskZ; // step to next level in source | |
| } | |
| break; | |
| } | |
| case 2: { | |
| const uint16_t *pSrc = (uint16_t *)pSrcBuff; | |
| uint16_t *pDestSlice = (uint16_t *)pDstBuff; | |
| for (uint z = 0; z < dwDepth; z++) { | |
| uint16_t *pDestRow = pDestSlice; | |
| DWORD dwY = dwStartY; | |
| for (uint y = 0; y < dwHeight; y++) { | |
| DWORD dwYZ = dwY | dwZ; | |
| DWORD dwX = dwStartX; | |
| for (uint x = 0; x < dwWidth; x++) { | |
| uint delta = dwX | dwYZ; | |
| pDestRow[x] = pSrc[delta]; // copy one pixel | |
| dwX = (dwX - dwMaskX) & dwMaskX; // step to next pixel in source | |
| } | |
| pDestRow += dwDstRowPitch / 2; // = dwBPP; // step to next line in destination | |
| dwY = (dwY - dwMaskY) & dwMaskY; // step to next line in source | |
| } | |
| pDestSlice += dwDstSlicePitch / 2; // = dwBPP; // step to next level in destination | |
| dwZ = (dwZ - dwMaskZ) & dwMaskZ; // step to next level in source | |
| } | |
| break; | |
| } | |
| case 4: { | |
| const uint32_t *pSrc = (uint32_t *)pSrcBuff; | |
| uint32_t *pDestSlice = (uint32_t *)pDstBuff; | |
| for (uint z = 0; z < dwDepth; z++) { | |
| uint32_t *pDestRow = pDestSlice; | |
| DWORD dwY = dwStartY; | |
| for (uint y = 0; y < dwHeight; y++) { | |
| DWORD dwYZ = dwY | dwZ; | |
| DWORD dwX = dwStartX; | |
| for (uint x = 0; x < dwWidth; x++) { | |
| uint delta = dwX | dwYZ; | |
| pDestRow[x] = pSrc[delta]; // copy one pixel | |
| dwX = (dwX - dwMaskX) & dwMaskX; // step to next pixel in source | |
| } | |
| pDestRow += dwDstRowPitch / 4; // = dwBPP; // step to next line in destination | |
| dwY = (dwY - dwMaskY) & dwMaskY; // step to next line in source | |
| } | |
| pDestSlice += dwDstSlicePitch / 4; // = dwBPP; // step to next level in destination | |
| dwZ = (dwZ - dwMaskZ) & dwMaskZ; // step to next level in source | |
| } | |
| break; | |
| } | |
| } | |
| } // EmuUnswizzleBox NOPATCH | |
| namespace XTL | |
| { | |
| const RenderStateInfo DxbxRenderStateInfo[] = { | |
| // String Ord Version Type Method Native | |
| { "D3DRS_PSALPHAINPUTS0" /*= 0*/, 3424, xtDWORD, NV2A_RC_IN_ALPHA(0) }, | |
| { "D3DRS_PSALPHAINPUTS1" /*= 1*/, 3424, xtDWORD, NV2A_RC_IN_ALPHA(1) }, | |
| { "D3DRS_PSALPHAINPUTS2" /*= 2*/, 3424, xtDWORD, NV2A_RC_IN_ALPHA(2) }, | |
| { "D3DRS_PSALPHAINPUTS3" /*= 3*/, 3424, xtDWORD, NV2A_RC_IN_ALPHA(3) }, | |
| { "D3DRS_PSALPHAINPUTS4" /*= 4*/, 3424, xtDWORD, NV2A_RC_IN_ALPHA(4) }, | |
| { "D3DRS_PSALPHAINPUTS5" /*= 5*/, 3424, xtDWORD, NV2A_RC_IN_ALPHA(5) }, | |
| { "D3DRS_PSALPHAINPUTS6" /*= 6*/, 3424, xtDWORD, NV2A_RC_IN_ALPHA(6) }, | |
| { "D3DRS_PSALPHAINPUTS7" /*= 7*/, 3424, xtDWORD, NV2A_RC_IN_ALPHA(7) }, | |
| { "D3DRS_PSFINALCOMBINERINPUTSABCD" /*= 8*/, 3424, xtDWORD, NV2A_RC_FINAL0 }, | |
| { "D3DRS_PSFINALCOMBINERINPUTSEFG" /*= 9*/, 3424, xtDWORD, NV2A_RC_FINAL1 }, | |
| { "D3DRS_PSCONSTANT0_0" /*= 10*/, 3424, xtD3DCOLOR, NV2A_RC_CONSTANT_COLOR0(0) }, | |
| { "D3DRS_PSCONSTANT0_1" /*= 11*/, 3424, xtD3DCOLOR, NV2A_RC_CONSTANT_COLOR0(1) }, | |
| { "D3DRS_PSCONSTANT0_2" /*= 12*/, 3424, xtD3DCOLOR, NV2A_RC_CONSTANT_COLOR0(2) }, | |
| { "D3DRS_PSCONSTANT0_3" /*= 13*/, 3424, xtD3DCOLOR, NV2A_RC_CONSTANT_COLOR0(3) }, | |
| { "D3DRS_PSCONSTANT0_4" /*= 14*/, 3424, xtD3DCOLOR, NV2A_RC_CONSTANT_COLOR0(4) }, | |
| { "D3DRS_PSCONSTANT0_5" /*= 15*/, 3424, xtD3DCOLOR, NV2A_RC_CONSTANT_COLOR0(5) }, | |
| { "D3DRS_PSCONSTANT0_6" /*= 16*/, 3424, xtD3DCOLOR, NV2A_RC_CONSTANT_COLOR0(6) }, | |
| { "D3DRS_PSCONSTANT0_7" /*= 17*/, 3424, xtD3DCOLOR, NV2A_RC_CONSTANT_COLOR0(7) }, | |
| { "D3DRS_PSCONSTANT1_0" /*= 18*/, 3424, xtD3DCOLOR, NV2A_RC_CONSTANT_COLOR1(0) }, | |
| { "D3DRS_PSCONSTANT1_1" /*= 19*/, 3424, xtD3DCOLOR, NV2A_RC_CONSTANT_COLOR1(1) }, | |
| { "D3DRS_PSCONSTANT1_2" /*= 20*/, 3424, xtD3DCOLOR, NV2A_RC_CONSTANT_COLOR1(2) }, | |
| { "D3DRS_PSCONSTANT1_3" /*= 21*/, 3424, xtD3DCOLOR, NV2A_RC_CONSTANT_COLOR1(3) }, | |
| { "D3DRS_PSCONSTANT1_4" /*= 22*/, 3424, xtD3DCOLOR, NV2A_RC_CONSTANT_COLOR1(4) }, | |
| { "D3DRS_PSCONSTANT1_5" /*= 23*/, 3424, xtD3DCOLOR, NV2A_RC_CONSTANT_COLOR1(5) }, | |
| { "D3DRS_PSCONSTANT1_6" /*= 24*/, 3424, xtD3DCOLOR, NV2A_RC_CONSTANT_COLOR1(6) }, | |
| { "D3DRS_PSCONSTANT1_7" /*= 25*/, 3424, xtD3DCOLOR, NV2A_RC_CONSTANT_COLOR1(7) }, | |
| { "D3DRS_PSALPHAOUTPUTS0" /*= 26*/, 3424, xtDWORD, NV2A_RC_OUT_ALPHA(0) }, | |
| { "D3DRS_PSALPHAOUTPUTS1" /*= 27*/, 3424, xtDWORD, NV2A_RC_OUT_ALPHA(1) }, | |
| { "D3DRS_PSALPHAOUTPUTS2" /*= 28*/, 3424, xtDWORD, NV2A_RC_OUT_ALPHA(2) }, | |
| { "D3DRS_PSALPHAOUTPUTS3" /*= 29*/, 3424, xtDWORD, NV2A_RC_OUT_ALPHA(3) }, | |
| { "D3DRS_PSALPHAOUTPUTS4" /*= 30*/, 3424, xtDWORD, NV2A_RC_OUT_ALPHA(4) }, | |
| { "D3DRS_PSALPHAOUTPUTS5" /*= 31*/, 3424, xtDWORD, NV2A_RC_OUT_ALPHA(5) }, | |
| { "D3DRS_PSALPHAOUTPUTS6" /*= 32*/, 3424, xtDWORD, NV2A_RC_OUT_ALPHA(6) }, | |
| { "D3DRS_PSALPHAOUTPUTS7" /*= 33*/, 3424, xtDWORD, NV2A_RC_OUT_ALPHA(7) }, | |
| { "D3DRS_PSRGBINPUTS0" /*= 34*/, 3424, xtDWORD, NV2A_RC_IN_RGB(0) }, | |
| { "D3DRS_PSRGBINPUTS1" /*= 35*/, 3424, xtDWORD, NV2A_RC_IN_RGB(1) }, | |
| { "D3DRS_PSRGBINPUTS2" /*= 36*/, 3424, xtDWORD, NV2A_RC_IN_RGB(2) }, | |
| { "D3DRS_PSRGBINPUTS3" /*= 37*/, 3424, xtDWORD, NV2A_RC_IN_RGB(3) }, | |
| { "D3DRS_PSRGBINPUTS4" /*= 38*/, 3424, xtDWORD, NV2A_RC_IN_RGB(4) }, | |
| { "D3DRS_PSRGBINPUTS5" /*= 39*/, 3424, xtDWORD, NV2A_RC_IN_RGB(5) }, | |
| { "D3DRS_PSRGBINPUTS6" /*= 40*/, 3424, xtDWORD, NV2A_RC_IN_RGB(6) }, | |
| { "D3DRS_PSRGBINPUTS7" /*= 41*/, 3424, xtDWORD, NV2A_RC_IN_RGB(7) }, | |
| { "D3DRS_PSCOMPAREMODE" /*= 42*/, 3424, xtDWORD, NV2A_TX_SHADER_CULL_MODE }, | |
| { "D3DRS_PSFINALCOMBINERCONSTANT0" /*= 43*/, 3424, xtDWORD, NV2A_RC_COLOR0 }, | |
| { "D3DRS_PSFINALCOMBINERCONSTANT1" /*= 44*/, 3424, xtDWORD, NV2A_RC_COLOR1 }, | |
| { "D3DRS_PSRGBOUTPUTS0" /*= 45*/, 3424, xtDWORD, NV2A_RC_OUT_RGB(0) }, | |
| { "D3DRS_PSRGBOUTPUTS1" /*= 46*/, 3424, xtDWORD, NV2A_RC_OUT_RGB(1) }, | |
| { "D3DRS_PSRGBOUTPUTS2" /*= 47*/, 3424, xtDWORD, NV2A_RC_OUT_RGB(2) }, | |
| { "D3DRS_PSRGBOUTPUTS3" /*= 48*/, 3424, xtDWORD, NV2A_RC_OUT_RGB(3) }, | |
| { "D3DRS_PSRGBOUTPUTS4" /*= 49*/, 3424, xtDWORD, NV2A_RC_OUT_RGB(4) }, | |
| { "D3DRS_PSRGBOUTPUTS5" /*= 50*/, 3424, xtDWORD, NV2A_RC_OUT_RGB(5) }, | |
| { "D3DRS_PSRGBOUTPUTS6" /*= 51*/, 3424, xtDWORD, NV2A_RC_OUT_RGB(6) }, | |
| { "D3DRS_PSRGBOUTPUTS7" /*= 52*/, 3424, xtDWORD, NV2A_RC_OUT_RGB(7) }, | |
| { "D3DRS_PSCOMBINERCOUNT" /*= 53*/, 3424, xtDWORD, NV2A_RC_ENABLE }, | |
| { "D3DRS_PS_RESERVED" /*= 54*/, 3424, xtDWORD, NV2A_NOP }, // Dxbx note : This takes the slot of X_D3DPIXELSHADERDEF.PSTextureModes, set by D3DDevice_SetRenderState_LogicOp? | |
| { "D3DRS_PSDOTMAPPING" /*= 55*/, 3424, xtDWORD, NV2A_TX_SHADER_DOTMAPPING }, | |
| { "D3DRS_PSINPUTTEXTURE" /*= 56*/, 3424, xtDWORD, NV2A_TX_SHADER_PREVIOUS }, | |
| // End of "pixel-shader" render states, continuing with "simple" render states : | |
| { "D3DRS_ZFUNC" /*= 57*/, 3424, xtD3DCMPFUNC, NV2A_DEPTH_FUNC, D3DRS_ZFUNC }, | |
| { "D3DRS_ALPHAFUNC" /*= 58*/, 3424, xtD3DCMPFUNC, NV2A_ALPHA_FUNC_FUNC, D3DRS_ALPHAFUNC }, | |
| { "D3DRS_ALPHABLENDENABLE" /*= 59*/, 3424, xtBOOL, NV2A_BLEND_FUNC_ENABLE, D3DRS_ALPHABLENDENABLE, "TRUE to enable alpha blending" }, | |
| { "D3DRS_ALPHATESTENABLE" /*= 60*/, 3424, xtBOOL, NV2A_ALPHA_FUNC_ENABLE, D3DRS_ALPHATESTENABLE, "TRUE to enable alpha tests" }, | |
| { "D3DRS_ALPHAREF" /*= 61*/, 3424, xtBYTE, NV2A_ALPHA_FUNC_REF, D3DRS_ALPHAREF }, | |
| { "D3DRS_SRCBLEND" /*= 62*/, 3424, xtD3DBLEND, NV2A_BLEND_FUNC_SRC, D3DRS_SRCBLEND }, | |
| { "D3DRS_DESTBLEND" /*= 63*/, 3424, xtD3DBLEND, NV2A_BLEND_FUNC_DST, D3DRS_DESTBLEND }, | |
| { "D3DRS_ZWRITEENABLE" /*= 64*/, 3424, xtBOOL, NV2A_DEPTH_WRITE_ENABLE, D3DRS_ZWRITEENABLE, "TRUE to enable Z writes" }, | |
| { "D3DRS_DITHERENABLE" /*= 65*/, 3424, xtBOOL, NV2A_DITHER_ENABLE, D3DRS_DITHERENABLE, "TRUE to enable dithering" }, | |
| { "D3DRS_SHADEMODE" /*= 66*/, 3424, xtD3DSHADEMODE, NV2A_SHADE_MODEL, D3DRS_SHADEMODE }, | |
| { "D3DRS_COLORWRITEENABLE" /*= 67*/, 3424, xtD3DCOLORWRITEENABLE, NV2A_COLOR_MASK, D3DRS_COLORWRITEENABLE }, // *_ALPHA, etc. per-channel write enable | |
| { "D3DRS_STENCILZFAIL" /*= 68*/, 3424, xtD3DSTENCILOP, NV2A_STENCIL_OP_ZFAIL, D3DRS_STENCILZFAIL, "Operation to do if stencil test passes and Z test fails" }, | |
| { "D3DRS_STENCILPASS" /*= 69*/, 3424, xtD3DSTENCILOP, NV2A_STENCIL_OP_ZPASS, D3DRS_STENCILPASS, "Operation to do if both stencil and Z tests pass" }, | |
| { "D3DRS_STENCILFUNC" /*= 70*/, 3424, xtD3DCMPFUNC, NV2A_STENCIL_FUNC_FUNC, D3DRS_STENCILFUNC }, | |
| { "D3DRS_STENCILREF" /*= 71*/, 3424, xtBYTE, NV2A_STENCIL_FUNC_REF, D3DRS_STENCILREF, "BYTE reference value used in stencil test" }, | |
| { "D3DRS_STENCILMASK" /*= 72*/, 3424, xtBYTE, NV2A_STENCIL_FUNC_MASK, D3DRS_STENCILMASK, "BYTE mask value used in stencil test" }, | |
| { "D3DRS_STENCILWRITEMASK" /*= 73*/, 3424, xtBYTE, NV2A_STENCIL_MASK, D3DRS_STENCILWRITEMASK, "BYTE write mask applied to values written to stencil buffer" }, | |
| { "D3DRS_BLENDOP" /*= 74*/, 3424, xtD3DBLENDOP, NV2A_BLEND_EQUATION, D3DRS_BLENDOP }, | |
| #ifdef DXBX_USE_D3D9 | |
| { "D3DRS_BLENDCOLOR" /*= 75*/, 3424, xtD3DCOLOR, NV2A_BLEND_COLOR, D3DRS_BLENDFACTOR, "D3DCOLOR for D3DBLEND_CONSTANTCOLOR" }, | |
| // D3D9 D3DRS_BLENDFACTOR : D3DCOLOR used for a constant blend factor during alpha blending for devices that support D3DPBLENDCAPS_BLENDFACTOR | |
| #else | |
| { "D3DRS_BLENDCOLOR" /*= 75*/, 3424, xtD3DCOLOR, NV2A_BLEND_COLOR, D3DRS_NONE, "D3DCOLOR for D3DBLEND_CONSTANTCOLOR" }, | |
| #endif | |
| { "D3DRS_SWATHWIDTH" /*= 76*/, 3424, xtD3DSWATH, NV2A_SWATH_WIDTH }, | |
| { "D3DRS_POLYGONOFFSETZSLOPESCALE" /*= 77*/, 3424, xtFloat, NV2A_POLYGON_OFFSET_FACTOR, D3DRS_NONE, "float Z factor for shadow maps" }, | |
| { "D3DRS_POLYGONOFFSETZOFFSET" /*= 78*/, 3424, xtFloat, NV2A_POLYGON_OFFSET_UNITS }, | |
| { "D3DRS_POINTOFFSETENABLE" /*= 79*/, 3424, xtBOOL, NV2A_POLYGON_OFFSET_POINT_ENABLE }, | |
| { "D3DRS_WIREFRAMEOFFSETENABLE" /*= 80*/, 3424, xtBOOL, NV2A_POLYGON_OFFSET_LINE_ENABLE }, | |
| { "D3DRS_SOLIDOFFSETENABLE" /*= 81*/, 3424, xtBOOL, NV2A_POLYGON_OFFSET_FILL_ENABLE }, | |
| { "D3DRS_DEPTHCLIPCONTROL" /*= 82*/, 4627, xtD3DDCC, NV2A_DEPTHCLIPCONTROL }, | |
| { "D3DRS_STIPPLEENABLE" /*= 83*/, 4627, xtBOOL, NV2A_POLYGON_STIPPLE_ENABLE }, | |
| { "D3DRS_SIMPLE_UNUSED8" /*= 84*/, 4627, xtDWORD, 0 }, | |
| { "D3DRS_SIMPLE_UNUSED7" /*= 85*/, 4627, xtDWORD, 0 }, | |
| { "D3DRS_SIMPLE_UNUSED6" /*= 86*/, 4627, xtDWORD, 0 }, | |
| { "D3DRS_SIMPLE_UNUSED5" /*= 87*/, 4627, xtDWORD, 0 }, | |
| { "D3DRS_SIMPLE_UNUSED4" /*= 88*/, 4627, xtDWORD, 0 }, | |
| { "D3DRS_SIMPLE_UNUSED3" /*= 89*/, 4627, xtDWORD, 0 }, | |
| { "D3DRS_SIMPLE_UNUSED2" /*= 90*/, 4627, xtDWORD, 0 }, | |
| { "D3DRS_SIMPLE_UNUSED1" /*= 91*/, 4627, xtDWORD, 0 }, | |
| // End of "simple" render states, continuing with "deferred" render states : | |
| { "D3DRS_FOGENABLE" /*= 92*/, 3424, xtBOOL, NV2A_FOG_ENABLE, D3DRS_FOGENABLE }, | |
| { "D3DRS_FOGTABLEMODE" /*= 93*/, 3424, xtD3DFOGMODE, NV2A_FOG_MODE, D3DRS_FOGTABLEMODE }, | |
| { "D3DRS_FOGSTART" /*= 94*/, 3424, xtFloat, NV2A_FOG_COORD_DIST, D3DRS_FOGSTART }, | |
| { "D3DRS_FOGEND" /*= 95*/, 3424, xtFloat, NV2A_FOG_MODE, D3DRS_FOGEND }, | |
| { "D3DRS_FOGDENSITY" /*= 96*/, 3424, xtFloat, NV2A_FOG_EQUATION_CONSTANT, D3DRS_FOGDENSITY }, // + NV2A_FOG_EQUATION_LINEAR + NV2A_FOG_EQUATION_QUADRATIC | |
| { "D3DRS_RANGEFOGENABLE" /*= 97*/, 3424, xtBOOL, NV2A_FOG_COORD_DIST, D3DRS_RANGEFOGENABLE }, | |
| { "D3DRS_WRAP0" /*= 98*/, 3424, xtD3DWRAP, NV2A_TX_WRAP(0), D3DRS_WRAP0 }, | |
| { "D3DRS_WRAP1" /*= 99*/, 3424, xtD3DWRAP, NV2A_TX_WRAP(1), D3DRS_WRAP1 }, | |
| { "D3DRS_WRAP2" /*= 100*/, 3424, xtD3DWRAP, NV2A_TX_WRAP(2), D3DRS_WRAP2 }, | |
| { "D3DRS_WRAP3" /*= 101*/, 3424, xtD3DWRAP, NV2A_TX_WRAP(3), D3DRS_WRAP3 }, | |
| { "D3DRS_LIGHTING" /*= 102*/, 3424, xtBOOL, NV2A_LIGHT_MODEL, D3DRS_LIGHTING }, // TODO : Needs push-buffer data conversion | |
| { "D3DRS_SPECULARENABLE" /*= 103*/, 3424, xtBOOL, NV2A_RC_FINAL0, D3DRS_SPECULARENABLE }, | |
| { "D3DRS_LOCALVIEWER" /*= 104*/, 3424, xtBOOL, 0, D3DRS_LOCALVIEWER }, | |
| { "D3DRS_COLORVERTEX" /*= 105*/, 3424, xtBOOL, 0, D3DRS_COLORVERTEX }, | |
| { "D3DRS_BACKSPECULARMATERIALSOURCE" /*= 106*/, 3424, xtD3DMCS, 0 }, // nsp. | |
| { "D3DRS_BACKDIFFUSEMATERIALSOURCE" /*= 107*/, 3424, xtD3DMCS, 0 }, // nsp. | |
| { "D3DRS_BACKAMBIENTMATERIALSOURCE" /*= 108*/, 3424, xtD3DMCS, 0 }, // nsp. | |
| { "D3DRS_BACKEMISSIVEMATERIALSOURCE" /*= 109*/, 3424, xtD3DMCS, 0 }, // nsp. | |
| { "D3DRS_SPECULARMATERIALSOURCE" /*= 110*/, 3424, xtD3DMCS, NV2A_COLOR_MATERIAL, D3DRS_SPECULARMATERIALSOURCE }, | |
| { "D3DRS_DIFFUSEMATERIALSOURCE" /*= 111*/, 3424, xtD3DMCS, 0, D3DRS_DIFFUSEMATERIALSOURCE }, | |
| { "D3DRS_AMBIENTMATERIALSOURCE" /*= 112*/, 3424, xtD3DMCS, 0, D3DRS_AMBIENTMATERIALSOURCE }, | |
| { "D3DRS_EMISSIVEMATERIALSOURCE" /*= 113*/, 3424, xtD3DMCS, 0, D3DRS_EMISSIVEMATERIALSOURCE }, | |
| { "D3DRS_BACKAMBIENT" /*= 114*/, 3424, xtD3DCOLOR, NV2A_LIGHT_MODEL_BACK_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R }, // ..NV2A_MATERIAL_FACTOR_BACK_B nsp. Was NV2A_LIGHT_MODEL_BACK_AMBIENT_R | |
| { "D3DRS_AMBIENT" /*= 115*/, 3424, xtD3DCOLOR, NV2A_LIGHT_MODEL_FRONT_SIDE_PRODUCT_AMBIENT_PLUS_EMISSION_R, D3DRS_AMBIENT }, // ..NV2A_LIGHT_MODEL_FRONT_AMBIENT_B + NV2A_MATERIAL_FACTOR_FRONT_R..NV2A_MATERIAL_FACTOR_FRONT_A Was NV2A_LIGHT_MODEL_FRONT_AMBIENT_R | |
| { "D3DRS_POINTSIZE" /*= 116*/, 3424, xtFloat, NV2A_POINT_PARAMETER(0), D3DRS_POINTSIZE }, | |
| { "D3DRS_POINTSIZE_MIN" /*= 117*/, 3424, xtFloat, 0, D3DRS_POINTSIZE_MIN }, | |
| { "D3DRS_POINTSPRITEENABLE" /*= 118*/, 3424, xtBOOL, NV2A_POINT_SMOOTH_ENABLE, D3DRS_POINTSPRITEENABLE }, | |
| { "D3DRS_POINTSCALEENABLE" /*= 119*/, 3424, xtBOOL, NV2A_POINT_PARAMETERS_ENABLE, D3DRS_POINTSCALEENABLE }, | |
| { "D3DRS_POINTSCALE_A" /*= 120*/, 3424, xtFloat, 0, D3DRS_POINTSCALE_A }, | |
| { "D3DRS_POINTSCALE_B" /*= 121*/, 3424, xtFloat, 0, D3DRS_POINTSCALE_B }, | |
| { "D3DRS_POINTSCALE_C" /*= 122*/, 3424, xtFloat, 0, D3DRS_POINTSCALE_C }, | |
| { "D3DRS_POINTSIZE_MAX" /*= 123*/, 3424, xtFloat, 0, D3DRS_POINTSIZE_MAX }, | |
| { "D3DRS_PATCHEDGESTYLE" /*= 124*/, 3424, xtDWORD, 0, D3DRS_PATCHEDGESTYLE }, // D3DPATCHEDGESTYLE? | |
| { "D3DRS_PATCHSEGMENTS" /*= 125*/, 3424, xtDWORD, 0, D3DRS_PATCHSEGMENTS }, | |
| // TODO -oDxbx : Is X_D3DRS_SWAPFILTER really a xtD3DMULTISAMPLE_TYPE? | |
| { "D3DRS_SWAPFILTER" /*= 126*/, 4361, xtD3DMULTISAMPLE_TYPE, 0, D3DRS_NONE, "D3DTEXF_LINEAR etc. filter to use for Swap" }, // nsp. | |
| { "D3DRS_PRESENTATIONINTERVAL" /*= 127*/, 4627, xtDWORD, 0 }, // nsp. | |
| { "D3DRS_DEFERRED_UNUSED8" /*= 128*/, 4627, xtDWORD, 0 }, | |
| { "D3DRS_DEFERRED_UNUSED7" /*= 129*/, 4627, xtDWORD, 0 }, | |
| { "D3DRS_DEFERRED_UNUSED6" /*= 130*/, 4627, xtDWORD, 0 }, | |
| { "D3DRS_DEFERRED_UNUSED5" /*= 131*/, 4627, xtDWORD, 0 }, | |
| { "D3DRS_DEFERRED_UNUSED4" /*= 132*/, 4627, xtDWORD, 0 }, | |
| { "D3DRS_DEFERRED_UNUSED3" /*= 133*/, 4627, xtDWORD, 0 }, | |
| { "D3DRS_DEFERRED_UNUSED2" /*= 134*/, 4627, xtDWORD, 0 }, | |
| { "D3DRS_DEFERRED_UNUSED1" /*= 135*/, 4627, xtDWORD, 0 }, | |
| // End of "deferred" render states, continuing with "complex" render states : | |
| { "D3DRS_PSTEXTUREMODES" /*= 136*/, 3424, xtDWORD, 0 }, | |
| { "D3DRS_VERTEXBLEND" /*= 137*/, 3424, xtD3DVERTEXBLENDFLAGS, NV2A_SKIN_MODE, D3DRS_VERTEXBLEND }, | |
| { "D3DRS_FOGCOLOR" /*= 138*/, 3424, xtD3DCOLOR, NV2A_FOG_COLOR, D3DRS_FOGCOLOR }, // SwapRgb | |
| { "D3DRS_FILLMODE" /*= 139*/, 3424, xtD3DFILLMODE, NV2A_POLYGON_MODE_FRONT, D3DRS_FILLMODE }, | |
| { "D3DRS_BACKFILLMODE" /*= 140*/, 3424, xtD3DFILLMODE, 0 }, // nsp. | |
| { "D3DRS_TWOSIDEDLIGHTING" /*= 141*/, 3424, xtBOOL, NV2A_POLYGON_MODE_BACK }, // nsp. | |
| { "D3DRS_NORMALIZENORMALS" /*= 142*/, 3424, xtBOOL, NV2A_NORMALIZE_ENABLE, D3DRS_NORMALIZENORMALS }, | |
| { "D3DRS_ZENABLE" /*= 143*/, 3424, xtBOOL, NV2A_DEPTH_TEST_ENABLE, D3DRS_ZENABLE }, // D3DZBUFFERTYPE? | |
| { "D3DRS_STENCILENABLE" /*= 144*/, 3424, xtBOOL, NV2A_STENCIL_ENABLE, D3DRS_STENCILENABLE }, | |
| { "D3DRS_STENCILFAIL" /*= 145*/, 3424, xtD3DSTENCILOP, NV2A_STENCIL_OP_FAIL, D3DRS_STENCILFAIL }, | |
| { "D3DRS_FRONTFACE" /*= 146*/, 3424, xtD3DFRONT, NV2A_FRONT_FACE }, // nsp. | |
| { "D3DRS_CULLMODE" /*= 147*/, 3424, xtD3DCULL, NV2A_CULL_FACE, D3DRS_CULLMODE }, | |
| { "D3DRS_TEXTUREFACTOR" /*= 148*/, 3424, xtD3DCOLOR, NV2A_RC_CONSTANT_COLOR0(0), D3DRS_TEXTUREFACTOR }, | |
| #ifdef DXBX_USE_D3D9 | |
| { "D3DRS_ZBIAS" /*= 149*/, 3424, xtLONG, 0, D3DRS_DEPTHBIAS }, | |
| #else | |
| { "D3DRS_ZBIAS" /*= 149*/, 3424, xtLONG, 0, D3DRS_ZBIAS }, | |
| #endif | |
| { "D3DRS_LOGICOP" /*= 150*/, 3424, xtD3DLOGICOP, NV2A_COLOR_LOGIC_OP_OP }, // nsp. | |
| #ifdef DXBX_USE_D3D9 | |
| { "D3DRS_EDGEANTIALIAS" /*= 151*/, 3424, xtBOOL, NV2A_LINE_SMOOTH_ENABLE, D3DRS_ANTIALIASEDLINEENABLE }, // Dxbx note : No Xbox ext. (according to Direct3D8) ! | |
| #else | |
| { "D3DRS_EDGEANTIALIAS" /*= 151*/, 3424, xtBOOL, NV2A_LINE_SMOOTH_ENABLE, D3DRS_EDGEANTIALIAS }, // Dxbx note : No Xbox ext. (according to Direct3D8) ! | |
| #endif | |
| { "D3DRS_MULTISAMPLEANTIALIAS" /*= 152*/, 3424, xtBOOL, NV2A_MULTISAMPLE_CONTROL, D3DRS_MULTISAMPLEANTIALIAS }, | |
| { "D3DRS_MULTISAMPLEMASK" /*= 153*/, 3424, xtDWORD, NV2A_MULTISAMPLE_CONTROL, D3DRS_MULTISAMPLEMASK }, | |
| // { "D3DRS_MULTISAMPLETYPE" /*= 154*/, 3424, xtD3DMULTISAMPLE_TYPE, 0 }, // [-3911] \_ aliasses D3DMULTISAMPLE_TYPE | |
| { "D3DRS_MULTISAMPLEMODE" /*= 154*/, 4361, xtD3DMULTISAMPLEMODE, 0 }, // [4361+] / D3DMULTISAMPLEMODE for the backbuffer | |
| { "D3DRS_MULTISAMPLERENDERTARGETMODE" /*= 155*/, 4242, xtD3DMULTISAMPLEMODE, NV2A_RT_FORMAT }, | |
| { "D3DRS_SHADOWFUNC" /*= 156*/, 3424, xtD3DCMPFUNC, NV2A_TX_RCOMP }, | |
| { "D3DRS_LINEWIDTH" /*= 157*/, 3424, xtFloat, NV2A_LINE_WIDTH }, | |
| { "D3DRS_SAMPLEALPHA" /*= 158*/, 4627, xtD3DSAMPLEALPHA, 0 }, // TODO : Later than 3424, but earlier then 4627? | |
| { "D3DRS_DXT1NOISEENABLE" /*= 159*/, 3424, xtBOOL, NV2A_CLEAR_DEPTH_VALUE }, | |
| { "D3DRS_YUVENABLE" /*= 160*/, 3911, xtBOOL, NV2A_CONTROL0 }, | |
| { "D3DRS_OCCLUSIONCULLENABLE" /*= 161*/, 3911, xtBOOL, NV2A_OCCLUDE_ZSTENCIL_EN }, | |
| { "D3DRS_STENCILCULLENABLE" /*= 162*/, 3911, xtBOOL, NV2A_OCCLUDE_ZSTENCIL_EN }, | |
| { "D3DRS_ROPZCMPALWAYSREAD" /*= 163*/, 3911, xtBOOL, 0 }, | |
| { "D3DRS_ROPZREAD" /*= 164*/, 3911, xtBOOL, 0 }, | |
| { "D3DRS_DONOTCULLUNCOMPRESSED" /*= 165*/, 3911, xtBOOL, 0 } | |
| }; | |
| /*Direct3D8 states unused : | |
| D3DRS_LINEPATTERN | |
| D3DRS_LASTPIXEL | |
| D3DRS_ZVISIBLE | |
| D3DRS_WRAP4 | |
| D3DRS_WRAP5 | |
| D3DRS_WRAP6 | |
| D3DRS_WRAP7 | |
| D3DRS_CLIPPING | |
| D3DRS_FOGVERTEXMODE | |
| D3DRS_CLIPPLANEENABLE | |
| D3DRS_SOFTWAREVERTEXPROCESSING | |
| D3DRS_DEBUGMONITORTOKEN | |
| D3DRS_INDEXEDVERTEXBLENDENABLE | |
| D3DRS_TWEENFACTOR | |
| D3DRS_POSITIONORDER | |
| D3DRS_NORMALORDER | |
| Direct3D9 states unused : | |
| D3DRS_SCISSORTESTENABLE = 174, | |
| D3DRS_SLOPESCALEDEPTHBIAS = 175, | |
| D3DRS_ANTIALIASEDLINEENABLE = 176, | |
| D3DRS_MINTESSELLATIONLEVEL = 178, | |
| D3DRS_MAXTESSELLATIONLEVEL = 179, | |
| D3DRS_ADAPTIVETESS_X = 180, | |
| D3DRS_ADAPTIVETESS_Y = 181, | |
| D3DRS_ADAPTIVETESS_Z = 182, | |
| D3DRS_ADAPTIVETESS_W = 183, | |
| D3DRS_ENABLEADAPTIVETESSELLATION = 184, | |
| D3DRS_TWOSIDEDSTENCILMODE = 185, // BOOL enable/disable 2 sided stenciling | |
| D3DRS_CCW_STENCILFAIL = 186, // D3DSTENCILOP to do if ccw stencil test fails | |
| D3DRS_CCW_STENCILZFAIL = 187, // D3DSTENCILOP to do if ccw stencil test passes and Z test fails | |
| D3DRS_CCW_STENCILPASS = 188, // D3DSTENCILOP to do if both ccw stencil and Z tests pass | |
| D3DRS_CCW_STENCILFUNC = 189, // D3DCMPFUNC fn. ccw Stencil Test passes if ((ref & mask) stencilfn (stencil & mask)) is true | |
| D3DRS_COLORWRITEENABLE1 = 190, // Additional ColorWriteEnables for the devices that support D3DPMISCCAPS_INDEPENDENTWRITEMASKS | |
| D3DRS_COLORWRITEENABLE2 = 191, // Additional ColorWriteEnables for the devices that support D3DPMISCCAPS_INDEPENDENTWRITEMASKS | |
| D3DRS_COLORWRITEENABLE3 = 192, // Additional ColorWriteEnables for the devices that support D3DPMISCCAPS_INDEPENDENTWRITEMASKS | |
| D3DRS_SRGBWRITEENABLE = 194, // Enable rendertarget writes to be DE-linearized to SRGB (for formats that expose D3DUSAGE_QUERY_SRGBWRITE) | |
| D3DRS_DEPTHBIAS = 195, | |
| D3DRS_WRAP8 = 198, // Additional wrap states for vs_3_0+ attributes with D3DDECLUSAGE_TEXCOORD | |
| D3DRS_WRAP9 = 199, | |
| D3DRS_WRAP10 = 200, | |
| D3DRS_WRAP11 = 201, | |
| D3DRS_WRAP12 = 202, | |
| D3DRS_WRAP13 = 203, | |
| D3DRS_WRAP14 = 204, | |
| D3DRS_WRAP15 = 205, | |
| D3DRS_SEPARATEALPHABLENDENABLE = 206, // TRUE to enable a separate blending function for the alpha channel | |
| D3DRS_SRCBLENDALPHA = 207, // SRC blend factor for the alpha channel when D3DRS_SEPARATEDESTALPHAENABLE is TRUE | |
| D3DRS_DESTBLENDALPHA = 208, // DST blend factor for the alpha channel when D3DRS_SEPARATEDESTALPHAENABLE is TRUE | |
| D3DRS_BLENDOPALPHA = 209 // Blending operation for the alpha channel when D3DRS_SEPARATEDESTALPHAENABLE is TRUE | |
| */ | |
| }; // end of namespace XTL | |
| #if 0 | |
| /* Generic swizzle function, usable for both x and y dimensions. | |
| When passing x, Max should be 2*height, and Shift should be 0 | |
| When passing y, Max should be width, and Shift should be 1 */ | |
| uint32 Swizzle(uint32 value, uint32 max, uint32 shift) | |
| { | |
| uint32 result; | |
| if (value < max) | |
| result = value; | |
| else | |
| result = value % max; | |
| // The following is based on http://graphics.stanford.edu/~seander/bithacks.html#InterleaveBMN : | |
| // --------------------------------11111111111111111111111111111111 | |
| result = (result | (result << 8)) & 0x00FF00FF; // 0000000000000000111111111111111100000000000000001111111111111111 | |
| result = (result | (result << 4)) & 0x0F0F0F0F; // 0000111100001111000011110000111100001111000011110000111100001111 | |
| result = (result | (result << 2)) & 0x33333333; // 0011001100110011001100110011001100110011001100110011001100110011 | |
| result = (result | (result << 1)) & 0x55555555; // 0101010101010101010101010101010101010101010101010101010101010101 | |
| result = result << shift; // y counts twice : 1010101010101010101010101010101010101010101010101010101010101010 | |
| if (value >= max) | |
| result += (value / max) * max * max >> (1 - shift); // x halves this | |
| return result; | |
| } | |
| typedef uint16 TRGB16; | |
| using namespace XTL; // for X_D3DFMT_* | |
| // test-case: Frogger, Turok, Crazy Taxi 3 and many more | |
| bool WndMain::ReadS3TCFormatIntoBitmap(uint32 format, unsigned char *data, uint32 dataSize, int width, int height, int pitch, void*& bitmap) | |
| { | |
| uint16 color[3]; | |
| TRGB32 color32b[4]; | |
| uint32 r, g, b, r1, g1, b1, pixelmap, j; | |
| int k, p, x, y; | |
| r = g = b = r1 = g1 = b1 = pixelmap = 0; | |
| j = k = p = x = y = 0; | |
| // sanity checks | |
| if (format != X_D3DFMT_DXT1 && format != X_D3DFMT_DXT3 && format != X_D3DFMT_DXT5) | |
| return false; | |
| if (!(width > 0) || !(height > 0)) | |
| return false; | |
| while (j < dataSize) { | |
| if (format != X_D3DFMT_DXT1) // Skip X_D3DFMT_DXT3 and X_D3DFMT_DXT5 alpha data (ported from Dxbx) | |
| j += 8; | |
| // Read two 16-bit pixels | |
| color[0] = (data[j + 0] << 0) + (data[j + 1] << 8); | |
| color[1] = (data[j + 2] << 0) + (data[j + 3] << 8); | |
| // Read 5+6+5 bit color channels and convert them to 8+8+8 bit : | |
| r = ((color[0] >> 11) & 31) * 255 / 31; | |
| g = ((color[0] >> 5) & 63) * 255 / 63; | |
| b = ((color[0]) & 31) * 255 / 31; | |
| r1 = ((color[1] >> 11) & 31) * 255 / 31; | |
| g1 = ((color[1] >> 5) & 63) * 255 / 63; | |
| b1 = ((color[1]) & 31) * 255 / 31; | |
| // Build first half of RGB32 color map : | |
| color32b[0].R = (unsigned char)r; | |
| color32b[0].G = (unsigned char)g; | |
| color32b[0].B = (unsigned char)b; | |
| color32b[1].R = (unsigned char)r1; | |
| color32b[1].G = (unsigned char)g1; | |
| color32b[1].B = (unsigned char)b1; | |
| // Build second half of RGB32 color map : | |
| if (color[0] > color[1]) | |
| { | |
| // Make up 2 new colors, 1/3 A + 2/3 B and 2/3 A + 1/3 B : | |
| color32b[2].R = (unsigned char)((r + r + r1 + 2) / 3); | |
| color32b[2].G = (unsigned char)((g + g + g1 + 2) / 3); | |
| color32b[2].B = (unsigned char)((b + b + b1 + 2) / 3); | |
| color32b[3].R = (unsigned char)((r + r1 + r1 + 2) / 3); | |
| color32b[3].G = (unsigned char)((g + g1 + g1 + 2) / 3); | |
| color32b[3].B = (unsigned char)((b + b1 + b1 + 2) / 3); | |
| } | |
| else | |
| { | |
| // Make up one new color : 1/2 A + 1/2 B : | |
| color32b[2].R = (unsigned char)((r + r1) / 2); | |
| color32b[2].G = (unsigned char)((g + g1) / 2); | |
| color32b[2].B = (unsigned char)((b + b1) / 2); | |
| color32b[3].R = (unsigned char)0; | |
| color32b[3].G = (unsigned char)0; | |
| color32b[3].B = (unsigned char)0; | |
| } | |
| x = (k / 2) % width; | |
| y = (k / 2) / width * 4; | |
| // Forza Motorsport needs this safety measure, as it has dataSize=147456, while we need 16384 bytes : | |
| if (y >= height) | |
| break; | |
| pixelmap = (data[j + 4] << 0) | |
| + (data[j + 5] << 8) | |
| + (data[j + 6] << 16) | |
| + (data[j + 7] << 24); | |
| for (p = 0; p < 16; p++) | |
| { | |
| ((TRGB32*)bitmap)[x + (p & 3) + (pitch / sizeof(TRGB32) * (y + (p >> 2)))] = color32b[pixelmap & 3]; | |
| pixelmap >>= 2; | |
| }; | |
| j += 8; | |
| k += 8; | |
| } | |
| return true; | |
| } | |
| // test-case: Baku Baku 2 (Homebrew) | |
| bool WndMain::ReadSwizzledFormatIntoBitmap(uint32 format, unsigned char *data, uint32 dataSize, int width, int height, int pitch, void*& bitmap) | |
| { | |
| uint32* xSwizzle; | |
| int x, y; | |
| uint32 ySwizzle; | |
| TRGB32* yscanline; | |
| // sanity checks | |
| if (format != X_D3DFMT_A8R8G8B8 && format != X_D3DFMT_X8R8G8B8) | |
| return false; | |
| if (!(width > 0) || !(height > 0)) | |
| return false; | |
| xSwizzle = (uint32*)malloc(sizeof(uint32) * width); | |
| if (xSwizzle == NULL) | |
| return false; | |
| for (x = 0; x < width; x++) | |
| xSwizzle[x] = Swizzle(x, (height * 2), 0); | |
| // Loop over all lines : | |
| for (y = 0; y < height; y++) | |
| { | |
| // Calculate y-swizzle : | |
| ySwizzle = Swizzle(y, width, 1); | |
| // Copy whole line in one go (using pre-calculated x-swizzle) : | |
| yscanline = &((TRGB32*)bitmap)[y*(pitch / sizeof(TRGB32))]; | |
| for (x = 0; x < width; x++) | |
| yscanline[x] = ((TRGB32*)data)[xSwizzle[x] + ySwizzle]; | |
| } | |
| free(xSwizzle); | |
| return true; | |
| } | |
| // UNTESTED - Need test-case! (Sorry I wasn't able to find a game using this format) | |
| bool WndMain::ReadSwizzled16bitFormatIntoBitmap(uint32 format, unsigned char *data, uint32 dataSize, int width, int height, int pitch, void*& bitmap) | |
| { | |
| uint32* xSwizzle; | |
| int x, y; | |
| uint32 ySwizzle; | |
| TRGB16* yscanline; | |
| // sanity checks | |
| if (format != X_D3DFMT_R5G6B5) | |
| return false; | |
| if (!(width > 0) || !(height > 0)) | |
| return false; | |
| xSwizzle = (uint32*)malloc(sizeof(uint32) * width); | |
| if (xSwizzle == NULL) | |
| return false; | |
| for (x = 0; x < width; x++) | |
| xSwizzle[x] = Swizzle(x, (height * 2), 0); | |
| // Loop over all lines : | |
| for (y = 0; y < height; y++) | |
| { | |
| // Calculate y-swizzle : | |
| ySwizzle = Swizzle(y, width, 1); | |
| // Copy whole line in one go (using pre-calculated x-swizzle) : | |
| yscanline = &((TRGB16*)bitmap)[y*(pitch / sizeof(TRGB16))]; | |
| for (x = 0; x < width; x++) | |
| yscanline[x] = ((TRGB16*)data)[xSwizzle[x] + ySwizzle]; | |
| } | |
| free(xSwizzle); | |
| return true; | |
| } | |
| #endif |