It looks like it is in fact possible to use DXT1 compressed textures in swizzled mode. When reading from swizzled DXT1, the GE reads 32 bytes of data (presumably since 4bpp in DXT1 expands to 16bpp uncompressed, giving the 128-byte swizzle block). The 4x4 pixel blocks are rearranged in the same manner as for uncompressed 16-bit textures, 8 pixels across by 8 down; so if you have a 32x8 texture (00, 01 etc. represent 4x4 pixel blocks):
Code: Select all
00 01 02 03 04 05 06 07
10 11 12 13 14 15 16 17
Code: Select all
00 01 10 11 02 03 12 13 04 05 14 15 06 07 16 17
If you're clever, you can interleave two textures within the same memory block (only two, since the GE requires 64-byte texture alignment):
Code: Select all
00 01 02 03 04 05 06 07 | AA AB AC AD AE AF AG AH
10 11 12 13 14 15 16 17 | BA BB BC BD BE BF BG BH
20 21 22 23 24 25 26 27 | CA CB CC CD CE CF CG CH
30 31 32 33 34 35 36 37 | DA DB DC DD DE DF DG DH
--- becomes ---
00 01 10 11 .. .. .. .. AA AB BA BB .. .. .. .. 02 03 12 13 .. .. .. .. AC AD BC BD .. .. .. ..
04 05 14 15 .. .. .. .. AE AF BE BF .. .. .. .. 06 07 16 17 .. .. .. .. AG AH BG BH .. .. .. ..
20 21 30 31 .. .. .. .. CA CB DA DB .. .. .. .. 22 23 32 33 .. .. .. .. CC CD DC DD .. .. .. ..
24 25 34 35 .. .. .. .. CE CF DE DF .. .. .. .. 26 27 36 37 .. .. .. .. CG CH DG DH .. .. .. ..
Code: Select all
00 01 02 03 04 05 06 07
10 11 12 13 14 15 16 17
20 21 22 23 24 25 26 27
30 31 32 33 34 35 36 37
40 41 42 43 44 45 46 47
50 51 52 53 54 55 56 57
60 61 62 63 64 65 66 67
70 71 72 73 74 75 76 77
--- becomes ---
00 01 10 11 20 21 30 31 40 41 50 51 60 61 70 71
02 03 12 13 22 23 32 33 42 43 52 53 62 63 72 73
04 05 14 15 24 25 34 35 44 45 54 55 64 65 74 75
06 07 16 17 26 27 36 37 46 47 56 57 66 67 76 77
FWIW, here's the code I use to swizzle:
Code: Select all
void swizzle_texture(const void * const src, void * const dest,
const int width, const int height, const int format)
{
// ...
if (format == GU_PSM_DXT1) {
// Note: the following assumes width%8 == 0
const int wblocks = width/8;
const int hblocks = (height+7)/8;
const uint8_t *sbase = (const uint8_t *)src;
uint32_t *dptr = (uint32_t *)dest;
int yblock;
for (yblock = 0; yblock < hblocks; yblock++, sbase += 2*(width*2)) {
const uint32_t *sptr0 = (const uint32_t *) sbase;
const uint32_t *sptr1 = (const uint32_t *)(sbase + width*2);
int xblock;
for (xblock = 0; xblock < wblocks;
xblock++, sptr0 += 4, sptr1 += 4, dptr += 32
) {
dptr[0] = sptr0[1]; // Swap words for the PSP
dptr[1] = sptr0[0];
dptr[2] = sptr0[3];
dptr[3] = sptr0[2];
dptr[4] = sptr1[1];
dptr[5] = sptr1[0];
dptr[6] = sptr1[3];
dptr[7] = sptr1[2];
}
if (height <= 32) {
dptr -= (32*wblocks) - 8; // Interleave rows
}
}
} // if (format == GU_PSM_DXT1)
}