Posts: 71
Threads: 3
Joined: Nov 2014
07-21-2017, 09:59 PM
(This post was last modified: 08-11-2017, 12:42 PM by gdkchan.)
This thread is an attempt to collect information about the new texture format used on the Nintendo Switch, BNTX (Binary Texture). It's different from formats used on previous nintendo consoles (like the WiiU and the 3DS, at least afaik).
I started to write a tool to extract textures from the bntx container. Currently, it supports the following formats (list not guaranteed to be up-to-date):
- BC1 (DXT1)
- BC2 (DXT3)
- BC3 (DXT5)
- BC4
- BC5
- RGBA8888
- RGB565
BNTX texture tool: https://github.com/gdkchan/BnTxx
I also made a tool to extract the Swich RomFS. Discussion about said container is out of the scope of this thread, but if anyone is interested, tool can be found here: https://gist.github.com/gdkchan/635187f5...53493f275f.
Overview of the format:
BNTX is basically a texture container. It can contain multiple textures, have a PATRICIA-trie based dictionary that allows quick access to textures using names as key, and also a relocation table that allows the binary to be loaded anywhere in memory and the addresses can be easily converted from relative offsets to absolute pointers.
Sections:
- BNTX Main header, contains pointers to the other sections, and also some lengths
- _STR String table section. First name is always an empty string "\0", used by the root node of the tree.
- _DIC Dictionary using the PATRICIA tree, each node have 16 bytes.
- BRTI Texture information. Contains one for each texture on the file.
- BRTD Texture data. BNTX contains only one of this section with all textures inside. Textures are aligned into 0x800 bytes blocks, and the 16 bytes header comes before the data.
- _RLT Relocation table, it's the last section on the file and contains the addresses for all pointers inside the file.
All the sections that starts with _ can be ignored if one just whiches to extract textures, because all data can be obtained from other sections too. The BRTD header can also be ignored because the only information it contains is the length of the data section (which is only useful if you're going to read it into memory and use the buffer directly).
Swizzling:
Switch textures uses swizzling, the DXT compressed textures have swizzling applied to the address of the 4x4 tiles, and on non-compressed textures, it is used on the address of each pixel. On the tile address, the bits from the X and Y coordinates are distributed using this pattern: yyyy x yy x y. However, after certain point it seems to use linear addressing, and this point is when either the numbers of available bits are over, or when the biggest tile size (which is 4/8/16/32x128, see below for details on the width/X pad) is hit. Take this information with a grain of salt, since it's not guaranteed (and most likely isn't) accurate.
Anyway, here is a real example (from a 512x512 dxt5 texture) that maybe can help you better understand the address format:
x x x x x y y y y x y y x y 0 0 0 0
Note that the entire address have 18 bits, which is the size of 512 * 512 - 1 = 0x3ffff. Since we're talking about dxt5 textures here, the lower 4 bits are the address inside the 16 bytes tile data block, this one is linear and you don't need to worry about it.
It will keep the pattern for the biggest tile size that can still fit inside the texture (see exception below). Which is 4x128 on a 2048x2048 (512x512 tiles) dxt5 texture for example, or 4x16 on a dx5 texture with something like 30x21 tiles. It decides whenever to round up or down based on the wasted height. Below you can find pseudo-code that shows how it's calculated:
Code: //Note: Perform rounding only if number is NOT a power of 2 already, otherwise the code below can be ignored entirely.
height_rounded_up = pow2_round_up(height)
height_rounded_down = pow2_round_down(height)
IF height <= height_rounded_down + height_rounded_down / 3 THEN
height = height_rounded_down
ELSE
height = height_rounded_up
END IF
For a 30x21 textura for example, a 4x16 block is used, while a 30x22 texture uses 4x32 blocks, and the texture data needs to be padded accordingly.
It's currently unknown if this only applies to compressed textures or all types, or even if this is accurate to what the hardware does, but this worked for all observed textures so far.
The "real swizzling" only seems to take place starting at bit 4. So, for example, dxt5 have 4 bits on the address for addressing inside the 16 bytes tile. On dxt1 on the other hand, each tile only uses 8 bytes, so only the lower 3 bits are used for addressing inside the tile. The extra "0" is filled with x. So, following the above swizzle, we have for dxt1:
... y y y y x y y x y x 0 0 0
And, for rgba8888, each pixel uses 4 bytes, so only the lower 2 bits are used for addressing inside the pixel color. We therefore have:
... y y y y x y y x y x x 0 0
For rgb565/rgb5551 and 16 bits formats:
... y y y y x y y x y x x x 0
and so on...
My current theory is that this was done to make hardware implementation simpler, maybe, since swizzling takes place at the same position, but since this is not my field I could be totally wrong here.
You can find a most likely shite implementation of the above swizzle here:
https://github.com/gdkchan/BnTxx/blob/ma...zleAddr.cs
Note that the upper bytes of the address uses linear addressing. So you need to calculate it as x + y * remaining_width, and shift the result to place it at the top bits. This is necessary for non-power of 2 textures.
Observed texture data width seems to be padded. On tiled textures, it seems to be padded so that the width is always a multiple of 4 (and 8 for 64 bits formats?). For RGBA8888, it seems to be padded to be a multiple of 16, and on RGB565/L8A8 a multiple of 32.
Some textures:
Those are some textures extracted from Puyo puyo tetris, the game I'm using to do this research, and also one of the few games that interests me on the Switch currently:
Any suggestion for improvement, correction or new information is welcomed.
TODO list:
- Figure out how non-compressed textures are swizzled (they seems to be encoded into 8x8 tile blocks but i'm not sure yet).
- Add support for more formats
- Support cubemap textures
07-22-2017, 09:41 AM
(This post was last modified: 07-22-2017, 10:44 AM by Random Talking Bush.)
Nice to see someone else working on the format and seeing what crap I'm having to go through right now with my own script. I'm pretty much in the same spot swizzling-wise (with non-tiled textures being incorrectly extracted), but allow me to give you a little push in the right direction while I'm getting my own QuickBMS script finished off. Here's a list of the formats I've come across -- the first byte's the actual format, and the second's for the variant:
Code: 0x02XX - R8
0x07XX - B5G6R5
0x09XX - R8G8
0x0AXX - R16
0x0BXX - R8G8B8A8
0x0FXX - R11G11B10
0x14XX - R32
0x1AXX - BC1 / DXT1
0x1BXX - BC2 / DXT3
0x1CXX - BC3 / DXT5
0x1DXX - BC4 / ATI1
0x1EXX - BC5 / ATI2
0x1FXX - BC6H
0x20XX - BC7
0xXX01 - _UNORM
0xXX02 - _SNORM
0xXX05 - _FLOAT
0xXX06 - _UNORM_SRGB
0xXX0A - _UF16
And as for some of the unknowns you have listed:
Code: Unknown14 = Actually two values. First two bytes I'm trying to figure out (and range from 0-3 and 5), but the second two are the amount of mipmaps (normally 0x01 for UI stuff).
Unknown30 = The amount of "faces" the image has (used for font files and cubemaps).
Unknown5C = Not sure if this is meant to be a long value or just a short, but 0x01 = Default texture, 0x03 = Cubemap, and 0x08 = CubemapFar.
Unknown0C, Unknown64 and Unknown6C (as well as the next four bytes after DataPtrAddress) are always 0 because they're 64-bit offsets.
I'm sure the finished product will be a lot better than anything I'll come up with, so keep it up!
Posts: 71
Threads: 3
Joined: Nov 2014
07-22-2017, 08:28 PM
(This post was last modified: 07-22-2017, 11:03 PM by gdkchan.)
(07-22-2017, 09:41 AM)Random Talking Bush Wrote: Nice to see someone else working on the format and seeing what crap I'm having to go through right now with my own script. I'm pretty much in the same spot swizzling-wise (with non-tiled textures being incorrectly extracted), but allow me to give you a little push in the right direction while I'm getting my own QuickBMS script finished off. Here's a list of the formats I've come across -- the first byte's the actual format, and the second's for the variant:
Code: 0x02XX - R8
0x07XX - B5G6R5
0x09XX - R8G8
0x0AXX - R16
0x0BXX - R8G8B8A8
0x0FXX - R11G11B10
0x14XX - R32
0x1AXX - BC1 / DXT1
0x1BXX - BC2 / DXT3
0x1CXX - BC3 / DXT5
0x1DXX - BC4 / ATI1
0x1EXX - BC5 / ATI2
0x1FXX - BC6H
0x20XX - BC7
0xXX01 - _UNORM
0xXX02 - _SNORM
0xXX05 - _FLOAT
0xXX06 - _UNORM_SRGB
0xXX0A - _UF16
And as for some of the unknowns you have listed:
Code: Unknown14 = Actually two values. First two bytes I'm trying to figure out (and range from 0-3 and 5), but the second two are the amount of mipmaps (normally 0x01 for UI stuff).
Unknown30 = The amount of "faces" the image has (used for font files and cubemaps).
Unknown5C = Not sure if this is meant to be a long value or just a short, but 0x01 = Default texture, 0x03 = Cubemap, and 0x08 = CubemapFar.
Unknown0C, Unknown64 and Unknown6C (as well as the next four bytes after DataPtrAddress) are always 0 because they're 64-bit offsets.
I'm sure the finished product will be a lot better than anything I'll come up with, so keep it up!
Thanks for the info. Would be nice if you could send me some sample files for each format so I can try to implement them on the tool. The only ones I could find on puyo puyo files was bc1, bc3 and rgba8888. I will try to implement the changes you suggested tomorrow.
Also, i'm not sure what you mean with non-tiled textures, but if you mean textures with non power of 2 sizes, I already fixed that and updated the source/post info to reflect the changes. I also added support for rgba8888 (swizzling is prety much the same).
Edit: Well, what you mean with non-tiles textures are the ones that doesnt uses compression Anyway I took a look at your format list, and for some formats (like dxt for example), storing data as float doesn't make sense (the only thing that can change on a dxt encoded block is the endianness of the data). So I guess some formats will always have this byte set to 1. Also not sure what UF16 (16 bits float a.k.a. Half Float I guess?).
07-23-2017, 09:06 AM
(This post was last modified: 07-24-2017, 06:19 AM by Random Talking Bush.)
(07-22-2017, 08:28 PM)gdkchan Wrote: Thanks for the info. Would be nice if you could send me some sample files for each format so I can try to implement them on the tool. The only ones I could find on puyo puyo files was bc1, bc3 and rgba8888. I will try to implement the changes you suggested tomorrow.
Also, i'm not sure what you mean with non-tiled textures, but if you mean textures with non power of 2 sizes, I already fixed that and updated the source/post info to reflect the changes. I also added support for rgba8888 (swizzling is prety much the same).
Edit: Well, what you mean with non-tiles textures are the ones that doesnt uses compression Anyway I took a look at your format list, and for some formats (like dxt for example), storing data as float doesn't make sense (the only thing that can change on a dxt encoded block is the endianness of the data). So I guess some formats will always have this byte set to 1. Also not sure what UF16 (16 bits float a.k.a. Half Float I guess?). Check your PMs, I sent you a bundle of 'em. And yeah, I guess I used the wrong term for those non-compressed textures, there, whoops!
And also yeah, UF16 is for half-floats (Unsigned Float, 16-bit). There's also SF16 which would be for signed half-floats, but I don't think it's used, or rather I haven't encountered any with it (as it is, there's barely any that I've seen with BC6H_UF16!).
Here's an updated list with all of the type combinations I've seen used in files:
Code: 0x0201 = R8_UNORM
0x0701 = B5G6R5_UNORM
0x0901 = R8A8_UNORM
0x0A01 = R16_UNORM
0x0B01 = R8G8B8A8_UNORM
0x0B06 = R8G8B8A8_UNORM_SRGB
0x0F05 = R11G11B10_FLOAT
0x1405 = R32_FLOAT
0x1A01 = BC1_UNORM / DXT1
0x1A06 = BC1_UNORM_SRGB
0x1B01 = BC2_UNORM / DXT3
0x1C01 = BC3_UNORM / DXT5
0x1C06 = BC3_UNORM_SRGB
0x1D01 = BC4_UNORM / ATI1
0x1D02 = BC4_SNORM
0x1E01 = BC5_UNORM / ATI2
0x1E02 = BC5_SNORM
0x1F0A = BC6H_UF16
0x2001 = BC7_UNORM
0x2006 = BC7_UNORM_SRGB
0x2D06 = ASTC (thanks, gdkchan!)
0x2F01 = UNKNOWN!
The last one in the list is one that's in the samples I've sent you. I have no idea what format it's supposed to be, everything I've tried just comes up with garbage (unless the texture itself's supposed to look like that, hrm).
(EDIT: Sent you another example with another unknown format that I found.)
Posts: 71
Threads: 3
Joined: Nov 2014
07-23-2017, 11:57 PM
(This post was last modified: 07-23-2017, 11:58 PM by gdkchan.)
Thanks for the files. I managed to fix some stuff and discover what some of the unknowns means with them. Extraction of non power of 2 textures is still hit or miss unfortunately, I still didn't totally figured out how the swizzle works, but its better at least. Tomorrow I plan to work to fix the remaining swizzling issues.
About the unknown formats you sent me, I took a look on the last one, and it's using ASTC compression. Heres one of them decoded (tc_MiiSuit_39^w):
This compressed format is still not supported on my tool (and i'm not on the mood to write a ASTC decompressor :I but I will end up doing it sooner or later anyway).
Posts: 71
Threads: 3
Joined: Nov 2014
07-24-2017, 10:22 PM
(This post was last modified: 07-25-2017, 03:36 PM by gdkchan.)
Well the other unknown format is also ASTC (but with a different block size). ASTC supports different block sizes, so I imagine that a bunch of formats starting at 0x2D are ASTC with different block sizes.
Trying to decode as if it used 5x5 blocks gives me this (SetMoonPhone_00^y):
So I believe that:
0x2D = ASTC 4x4 block
0x2F = ASTC 5x5 blocks
Btw did you have any luck figuring out how the swizzle works on non pow2 textures?
Edit: Updated because I was able to decode the texture properly. Also, I believe that starting from 0x2D, those are the texture formats:
0x2D ASTC 4x4 block
0x2E ASTC 5x4 block
0x2F ASTC 5x5 block
0x30 ASTC 6x5 block
0x31 ASTC 6x6 block
0x32 ASTC 8x5 block
0x33 ASTC 8x6 block
0x34 ASTC 8x8 block
0x35 ASTC 10x5 block
0x36 ASTC 10x6 block
0x37 ASTC 10x8 block
0x38 ASTC 10x10 block
0x39 ASTC 12x10 block
0x3A ASTC 12x12 block
Of course, I was only able to test two of those. If you find the some of the other possible ASTC formats, we can confirm this theory.
Posts: 14
Threads: 0
Joined: Aug 2016
07-26-2017, 11:15 AM
(This post was last modified: 07-26-2017, 11:16 AM by KillzXGaming.)
Nice work on the tool! I'm not sure if you've looked into BC4 textures yet, though i've taken a look at some BC4 textures myself and it seems that they're missing the green and blue channels.
Here is DK's texture in MK8D
http://i.imgur.com/Pl9l9r9.png
And in original MK8 for wii u.
http://i.imgur.com/RcL7Hat.png
07-26-2017, 11:39 AM
(This post was last modified: 07-26-2017, 11:47 AM by Random Talking Bush.)
(07-26-2017, 11:15 AM)KillzXGaming Wrote: Nice work on the tool! I'm not sure if you've looked into BC4 textures yet, though i've taken a look at some BC4 textures myself and it seems that they're missing the green and blue channels.
Here is DK's texture in MK8D
http://i.imgur.com/Pl9l9r9.png
And in original MK8 for wii u.
http://i.imgur.com/RcL7Hat.png Well, BC4 is just a greyscaled image anyway, so the green and blue would be identical to the red channel.
(07-24-2017, 10:22 PM)gdkchan Wrote: Btw did you have any luck figuring out how the swizzle works on non pow2 textures? The way I've got it for my QuickBMS script right now is incredibly hacky and frankly I'm not even sure how it's working, so I can't say for sure.
Posts: 14
Threads: 0
Joined: Aug 2016
Ah yes true. Does appear to be identical to original if i copy to the other channels.
Also another note, BC5 textures in this case used as normal maps seem to look quite strange.
http://i.imgur.com/j9DzRIV.png
Original
http://i.imgur.com/RVVIw0T.png
Posts: 71
Threads: 3
Joined: Nov 2014
07-26-2017, 01:10 PM
(This post was last modified: 07-26-2017, 01:32 PM by gdkchan.)
(07-26-2017, 12:15 PM)KillzXGaming Wrote: Ah yes true. Does appear to be identical to original if i copy to the other channels.
Also another note, BC5 textures in this case used as normal maps seem to look quite strange.
http://i.imgur.com/j9DzRIV.png
Original
http://i.imgur.com/RVVIw0T.png
Well, normals are unit vectors, so on BC5 the Z component is not stored on the texture, only X and Y. Then Z is calculated based on X and Y (since X² + Y² + Z² are always 1 on unit vectors, Z can be computed as sqrt(1 - (X² + Y²)). Those blocks does seems weird through, its probably because the sign [-1, 1] is not being interpreted correctly. The way fragment shader expects is usually 0 being -1, and 255 being 1, but on a signed byte it's mapped as 128 = -1, 0 = 0 and 127 = 1. Not sure if this is the problem through.
Anyway I didn't looked into this yet, My focus currently is getting the swizzle correct for all textures, and then I'll start working on each pixel format. But thanks for pointing out this issue, I'll try to fix it as soon as I have the swizzle fully working.
(07-26-2017, 11:39 AM)Random Talking Bush Wrote: The way I've got it for my QuickBMS script right now is incredibly hacky and frankly I'm not even sure how it's working, so I can't say for sure.
This seems to be quite a interesting piece of code. I kind of isolated the problem I have with the swizzle currently, and also managed to understand a little better how it is supposed to work.
The easiest way I found to understand the ordering was this:
We first we have a 2x2 block. I will call it the "small block". Each small block contains 4 (2x2) tiles, and is ordered like this:
Code: +--+--+
|0 |2 |
+--+--+
|1 |3 |
+--+--+
Then, we have a 2x4 block. Let's call it the "medium block". Each medium block contains 8 (2x4) small blocks, and is ordered like this:
Code: +----+----+
|0 |4 |
| | |
+----+----+
|1 |5 |
| | |
+----+----+
|2 |6 |
| | |
+----+----+
|3 |7 |
| | |
+----+----+
And then we have a 2x16 block, a "large block". Each large block contains 32 (2x16) medium blocks. The ordering follows the same pattern of the previous blocks, and this is the biggest swizzled block that a texture can contain (at least on the files I observed). When the image is smaller than the block size (for example, images with less than 128 pixels of height (or 512 for 4x4 tiles compressed textures), then the block is ignored, and swizzle is performed just on the block sizes that does "fit" inside the texture.
So, basically my current problem is - what happens when the image size is not a multiple of those block sizes? Or when they don't have a power of 2 size?
The following textures can be decoded fine:
- Size is power of 2
- Width and height are greater than 128 (or 512 for compressed textures)
All other cases may or may not work properly.
I also generated mapping for some of the texture sizes for analysis.
From a 64x66 texture, rounded to 64x96:
Code: 0 2 16 18 64 66 80 82 128 130 144 146 192 194 208 210
1 3 17 19 65 67 81 83 129 131 145 147 193 195 209 211
4 6 20 22 68 70 84 86 132 134 148 150 196 198 212 214
5 7 21 23 69 71 85 87 133 135 149 151 197 199 213 215
8 10 24 26 72 74 88 90 136 138 152 154 200 202 216 218
9 11 25 27 73 75 89 91 137 139 153 155 201 203 217 219
12 14 28 30 76 78 92 94 140 142 156 158 204 206 220 222
13 15 29 31 77 79 93 95 141 143 157 159 205 207 221 223
32 34 48 50 96 98 112 114 160 162 176 178 224 226 240 242
33 35 49 51 97 99 113 115 161 163 177 179 225 227 241 243
36 38 52 54 100 102 116 118 164 166 180 182 228 230 244 246
37 39 53 55 101 103 117 119 165 167 181 183 229 231 245 247
40 42 56 58 104 106 120 122 168 170 184 186 232 234 248 250
41 43 57 59 105 107 121 123 169 171 185 187 233 235 249 251
44 46 60 62 108 110 124 126 172 174 188 190 236 238 252 254
45 47 61 63 109 111 125 127 173 175 189 191 237 239 253 255
256 258 272 274 320 322 336 338 384 386 400 402 448 450 464 466
257 259 273 275 321 323 337 339 385 387 401 403 449 451 465 467
260 262 276 278 324 326 340 342 388 390 404 406 452 454 468 470
261 263 277 279 325 327 341 343 389 391 405 407 453 455 469 471
264 266 280 282 328 330 344 346 392 394 408 410 456 458 472 474
265 267 281 283 329 331 345 347 393 395 409 411 457 459 473 475
268 270 284 286 332 334 348 350 396 398 412 414 460 462 476 478
269 271 285 287 333 335 349 351 397 399 413 415 461 463 477 479
From a 86x174? texture rounded to 96x192:
Code: 0 2 16 18 256 258 272 274 512 514 528 530 768 770 784 786 1024 1026 1040 1042 1280 1282 1296 1298
1 3 17 19 257 259 273 275 513 515 529 531 769 771 785 787 1025 1027 1041 1043 1281 1283 1297 1299
4 6 20 22 260 262 276 278 516 518 532 534 772 774 788 790 1028 1030 1044 1046 1284 1286 1300 1302
5 7 21 23 261 263 277 279 517 519 533 535 773 775 789 791 1029 1031 1045 1047 1285 1287 1301 1303
8 10 24 26 264 266 280 282 520 522 536 538 776 778 792 794 1032 1034 1048 1050 1288 1290 1304 1306
9 11 25 27 265 267 281 283 521 523 537 539 777 779 793 795 1033 1035 1049 1051 1289 1291 1305 1307
12 14 28 30 268 270 284 286 524 526 540 542 780 782 796 798 1036 1038 1052 1054 1292 1294 1308 1310
13 15 29 31 269 271 285 287 525 527 541 543 781 783 797 799 1037 1039 1053 1055 1293 1295 1309 1311
32 34 48 50 288 290 304 306 544 546 560 562 800 802 816 818 1056 1058 1072 1074 1312 1314 1328 1330
33 35 49 51 289 291 305 307 545 547 561 563 801 803 817 819 1057 1059 1073 1075 1313 1315 1329 1331
36 38 52 54 292 294 308 310 548 550 564 566 804 806 820 822 1060 1062 1076 1078 1316 1318 1332 1334
37 39 53 55 293 295 309 311 549 551 565 567 805 807 821 823 1061 1063 1077 1079 1317 1319 1333 1335
40 42 56 58 296 298 312 314 552 554 568 570 808 810 824 826 1064 1066 1080 1082 1320 1322 1336 1338
41 43 57 59 297 299 313 315 553 555 569 571 809 811 825 827 1065 1067 1081 1083 1321 1323 1337 1339
44 46 60 62 300 302 316 318 556 558 572 574 812 814 828 830 1068 1070 1084 1086 1324 1326 1340 1342
45 47 61 63 301 303 317 319 557 559 573 575 813 815 829 831 1069 1071 1085 1087 1325 1327 1341 1343
64 66 80 82 320 322 336 338 576 578 592 594 832 834 848 850 1088 1090 1104 1106 1344 1346 1360 1362
65 67 81 83 321 323 337 339 577 579 593 595 833 835 849 851 1089 1091 1105 1107 1345 1347 1361 1363
68 70 84 86 324 326 340 342 580 582 596 598 836 838 852 854 1092 1094 1108 1110 1348 1350 1364 1366
69 71 85 87 325 327 341 343 581 583 597 599 837 839 853 855 1093 1095 1109 1111 1349 1351 1365 1367
72 74 88 90 328 330 344 346 584 586 600 602 840 842 856 858 1096 1098 1112 1114 1352 1354 1368 1370
73 75 89 91 329 331 345 347 585 587 601 603 841 843 857 859 1097 1099 1113 1115 1353 1355 1369 1371
76 78 92 94 332 334 348 350 588 590 604 606 844 846 860 862 1100 1102 1116 1118 1356 1358 1372 1374
77 79 93 95 333 335 349 351 589 591 605 607 845 847 861 863 1101 1103 1117 1119 1357 1359 1373 1375
96 98 112 114 352 354 368 370 608 610 624 626 864 866 880 882 1120 1122 1136 1138 1376 1378 1392 1394
97 99 113 115 353 355 369 371 609 611 625 627 865 867 881 883 1121 1123 1137 1139 1377 1379 1393 1395
100 102 116 118 356 358 372 374 612 614 628 630 868 870 884 886 1124 1126 1140 1142 1380 1382 1396 1398
101 103 117 119 357 359 373 375 613 615 629 631 869 871 885 887 1125 1127 1141 1143 1381 1383 1397 1399
104 106 120 122 360 362 376 378 616 618 632 634 872 874 888 890 1128 1130 1144 1146 1384 1386 1400 1402
105 107 121 123 361 363 377 379 617 619 633 635 873 875 889 891 1129 1131 1145 1147 1385 1387 1401 1403
108 110 124 126 364 366 380 382 620 622 636 638 876 878 892 894 1132 1134 1148 1150 1388 1390 1404 1406
109 111 125 127 365 367 381 383 621 623 637 639 877 879 893 895 1133 1135 1149 1151 1389 1391 1405 1407
128 130 144 146 384 386 400 402 640 642 656 658 896 898 912 914 1152 1154 1168 1170 1408 1410 1424 1426
129 131 145 147 385 387 401 403 641 643 657 659 897 899 913 915 1153 1155 1169 1171 1409 1411 1425 1427
132 134 148 150 388 390 404 406 644 646 660 662 900 902 916 918 1156 1158 1172 1174 1412 1414 1428 1430
133 135 149 151 389 391 405 407 645 647 661 663 901 903 917 919 1157 1159 1173 1175 1413 1415 1429 1431
136 138 152 154 392 394 408 410 648 650 664 666 904 906 920 922 1160 1162 1176 1178 1416 1418 1432 1434
137 139 153 155 393 395 409 411 649 651 665 667 905 907 921 923 1161 1163 1177 1179 1417 1419 1433 1435
140 142 156 158 396 398 412 414 652 654 668 670 908 910 924 926 1164 1166 1180 1182 1420 1422 1436 1438
141 143 157 159 397 399 413 415 653 655 669 671 909 911 925 927 1165 1167 1181 1183 1421 1423 1437 1439
160 162 176 178 416 418 432 434 672 674 688 690 928 930 944 946 1184 1186 1200 1202 1440 1442 1456 1458
161 163 177 179 417 419 433 435 673 675 689 691 929 931 945 947 1185 1187 1201 1203 1441 1443 1457 1459
164 166 180 182 420 422 436 438 676 678 692 694 932 934 948 950 1188 1190 1204 1206 1444 1446 1460 1462
165 167 181 183 421 423 437 439 677 679 693 695 933 935 949 951 1189 1191 1205 1207 1445 1447 1461 1463
168 170 184 186 424 426 440 442 680 682 696 698 936 938 952 954 1192 1194 1208 1210 1448 1450 1464 1466
169 171 185 187 425 427 441 443 681 683 697 699 937 939 953 955 1193 1195 1209 1211 1449 1451 1465 1467
172 174 188 190 428 430 444 446 684 686 700 702 940 942 956 958 1196 1198 1212 1214 1452 1454 1468 1470
173 175 189 191 429 431 445 447 685 687 701 703 941 943 957 959 1197 1199 1213 1215 1453 1455 1469 1471
Both are extracted correctly with those patterns, but they were generated using different code, and they are also different. So I basically, don't know why this difference exists, and I'm currently trying to make some sense out of it. I spent some time yesterday trying different solutions, but none of them worked for all samples.
Also, another thing to take into account: Unused values = space waste. Basically, for a 64x66 textures, this would mean 64x62 pixels worth of wasted space on the file, however this is not what it does, it never wastes so much space. I would expect it to round the texture down to 64x32 then address the top bits linearly, but that doesn't seems to be the case either - rounding it down fixes some textures but break others.
Posts: 10
Threads: 0
Joined: Oct 2015
I made a BNTX extractor (in which the swizzling is based on your algorithm, but with slight improvements) and every texture I tried works fine.
Posts: 71
Threads: 3
Joined: Nov 2014
07-26-2017, 10:37 PM
(This post was last modified: 07-26-2017, 10:40 PM by gdkchan.)
(07-26-2017, 03:23 PM)aboood40091 Wrote: I made a BNTX extractor (in which the swizzling is based on your algorithm, but with slight improvements) and every texture I tried works fine. Nice one! I took a look on the repo, and the readme says "format used in Wii U games" but I guess you meant "Switch games", just a note.
Also, the swizzling issue only affected a few textures. But well, good news is that I (think) that I managed to fix it. At least it's working on all samples I have here, yay! What I discovered using trial and error, was that the wrong textures was always on the same height range. Basically, if we have for example, a texture with height 68. We will need to round it up to calculate the number of bits for each coord value (X and Y), so we get 128. If we subtract 128 - 68 we get the wasted space height, so basically 60. Looks like that it uses some threshold to decide whenever to round up or down based on that. If the wasted height is greater than 2/3 of the rounded down height (in this case 64), it seems to round down, otherwise it rounds up. Now tbh, this seems a bit weird, but all the tests I did so far indicates that this is the right thing to do. With this code in place, all the swizzle issues I knew of are now gone. The code on github is already updated, and if anyone find any swizzle issues just let me know.
I will try to fix the issues pointed by KillzXGaming tomorrow.
Posts: 71
Threads: 3
Joined: Nov 2014
(07-26-2017, 12:15 PM)KillzXGaming Wrote: Ah yes true. Does appear to be identical to original if i copy to the other channels.
Also another note, BC5 textures in this case used as normal maps seem to look quite strange.
http://i.imgur.com/j9DzRIV.png
Original
http://i.imgur.com/RVVIw0T.png
This should be fixed now.
Found another unknown format in Splatoon 2, 0x3106, which seems to be ASTC-based. I sent it to you to check out at your own leisure.
Posts: 71
Threads: 3
Joined: Nov 2014
(08-05-2017, 01:48 AM)Random Talking Bush Wrote: Found another unknown format in Splatoon 2, 0x3106, which seems to be ASTC-based. I sent it to you to check out at your own leisure. Thanks for the files. They are already supported by the tool actually (sort of), my assumption seems to be correct.
|