Jump to content

Space Marine 2 pct_mip / pct.resource textures


Go to solution Solved by haus,

Recommended Posts

Space Marine 2 uses Saber Interactive's Swarm Engine.

It uses a few of Saber's pct textures, with the vast majority being pct_mip.
From what I understand, the pct_mip is raw texture data with the pct.resource specifying how it is read.
pct.resource files can be read as plain text.

The existing QCTools/QCPCT tool is not able to read the SM2 textures, from what I have found.
https://github.com/iOrange/QCTools

Samples https://drive.google.com/drive/folders/19dmtmLcdLUzA7Z8Y-IkJVZUrB7OQetbQ?usp=sharing

ch_termagaunt_head.pct.resource

Spoiler

__type: res_desc_pct
header:
  faceSize: 1398096
  format: 51
  mipLevel:
  - offset: 0
    size: 1048576
  - offset: 1048576
    size: 262144
  - offset: 1310720
    size: 65536
  - offset: 1376256
    size: 16384
  - offset: 1392640
    size: 4096
  - offset: 1396736
    size: 1024
  - offset: 1397760
    size: 256
  - offset: 1398016
    size: 64
  - offset: 1398080
    size: 16
  nFaces: 1
  nMipMap: 9
  sign: 1346978644
  size: 1398096
  sx: 1024
  sy: 1024
  sz: 1
imageOffset: 0
isCopyDst: false
isImposter: false
isLightmap: false
linkTd: res://td/ch_termagaunt_head.td.resource
mipMaps:
- ch_termagaunt_head_0.pct_mip
- ch_termagaunt_head_1.pct_mip
- ch_termagaunt_head_2.pct_mip
- ch_termagaunt_head_3.pct_mip
- ch_termagaunt_head_4.pct_mip
- ch_termagaunt_head_5.pct_mip
- ch_termagaunt_head_6.pct_mip
- ch_termagaunt_head_7.pct_mip
- ch_termagaunt_head_8.pct_mip
pct: ''
source: <source>\characters\ch_termagaunt_head.tga
texName: ch_termagaunt_head
texType: ''
tileLayout: 0
tiles: []
useHeaderFromResource: true

 

Edited by 09williamsad
Link to comment
Share on other sites

On 9/8/2024 at 12:08 PM, 09williamsad said:

From what I understand, the pct_mip is raw texture data with the pct.resource specifying how it is read.

Yeah, given ch_termagaunt_head_0.pct_mip's exact size of 1048576 bytes (1024x1024), it's evidently headerless and doesn't use variable length compression (could still use block-based compression though, like BC*/DXT*/ATSC/ETC/PVR, depending on which target hardware). At 1024 8-bpp pixels wide, you can see some vertical patterns align (whereas at 1023 or 1025, they appear diagonally shifted), but the overall image doesn't look like much 🤷. It could be a case of encryption atop a block-based format. 🤔 (update) It's BC7, the complicated one. It's curious that there are histogram spikes at 40h, 7Fh, 80h, and FFh.

image.png.70bf3b151012a0f0a83d6e8c9753da51.png

(update after haus's reply)

image.png.05f2781bc7df2231f31842fb96cb2132.png

Edited by piken
Update after haus's reply.
Link to comment
Share on other sites

  • Solution

ch_soldier_head_01_BC7_UNORM.thumb.jpg.1d22c5e3801b64ddf390d6764eade0d7.jpg

 

EDIT: Yep, just get the info from the .pct.resource file, clobber all of the .pct_mip files together into a single stream, and use something to re-create the DX header.

Formats:

Spoiler
0x00 | 00 = ARGB8888
0x01 | 01 = ARGB4444
0x02 | 02 = RGB888
0x03 | 03 = A8
0x04 | 04 = RGB332
0x05 | 05 = RGB565
0x06 | 06 = ARGB8332
0x07 | 07 = ARGB1555
0x08 | 08 = I8
0x09 | 09 = AI44
0x0A | 10 = AI88
0x0B | 11 = UV88
0x0C | 12 = OXT1
0x0D | 13 = AXT1
0x0E | 14 = XT2
0x0F | 15 = XT3
0x10 | 16 = XT4
0x11 | 17 = XT5
0x12 | 18 = PAL_8
0x13 | 19 = PAL_4
0x14 | 20 = PAL_A8
0x15 | 21 = PAL_A4
0x16 | 22 = XRGB8888
0x17 | 23 = ARGB7888R
0x18 | 24 = ARGB1555R
0x19 | 25 = RGB555R
0x1A | 26 = RGB888R
0x1B | 27 = SWZ_ARGB8888
0x1C | 28 = SWZ_ARGB4444
0x1D | 29 = SWZ_RGB888
0x1E | 30 = SWZ_RGB565
0x1F | 31 = SWZ_ARGB1555
0x20 | 32 = SWZ_UV88
0x21 | 33 = SWZ_XRGB8888
0x22 | 34 = SWZ_PAL_8
0x23 | 35 = SWZ_PAL_A8
0x24 | 36 = DXN
0x25 | 37 = DXT5A
0x26 | 38 = RGBA16161616F
0x27 | 39 = ARGB16161616S
0x28 | 40 = ARGB16161616U
0x29 | 41 = R16F
0x2A | 42 = R32F
0x2B | 43 = RGB323232F
0x2C | 44 = SWZ_ARGB8888U
0x2D | 45 = R9G9B9E5_SHAREDEXP
0x2E | 46 = R8U
0x2F | 47 = R10G10B10A2_UNORM
0x30 | 48 = R32U
0x31 | 49 = BC6U
0x32 | 50 = BC6S
0x33 | 51 = BC7
0x34 | 52 = BC7A
0x35 | 53 = R16G16F
0x36 | 54 = R16G16
0x37 | 55 = R16
0x38 | 56 = R32G32U
0x39 | 57 = RGBA32323232F
0x3A | 58 = R32G32B32A32U
0x3B | 59 = R32G32B32A32S
0x3C | 60 = R32G32B32U
0x3D | 61 = R32G32B332S
0x3E | 62 = R16G16U
0x3F | 63 = R8G8U
0x40 | 64 = SWZ_ARGB8888S

 

 

Attached is a C# code example that uses DirectXTexNet to recreate the header.

SM2 Tex.zip

Edited by haus
added all format mappings
  • Like 1
  • Thanks 1
Link to comment
Share on other sites

On 9/18/2024 at 12:13 PM, haus said:

EDIT: Yep, just get the info from the .pct.resource file, clobber all of the .pct_mip files together into a single stream, and use something to re-create the DX header.

Hi, I'm a super newbie just starting to touch the grass for texture editing for SM2.  Can you help walk me through how to clobber all the .pct_mip files together + re-create the DX header.  Sorry if this is too much trouble, but I am a new to this step and am having trouble finding resources to learn.

Thanks ❤️

Link to comment
Share on other sites

On 9/19/2024 at 12:13 AM, haus said:

EDIT: Yep, just get the info from the .pct.resource file, clobber all of the .pct_mip files together into a single stream, and use something to re-create the DX header.

 

The means the reverse of this would be to split the exported the single texture file to # (depending on the .pct.resource) .pct_mip files.

No need to do any anyting else? Since the data is in the .pct.resource file?

EDIT: Wait...

You don't even really need to do that for textures...

Anyway thanks man. Helped a ton.

https://streamable.com/tck37o

image.thumb.png.64328dc4b87c5c36990432d3acab9965.png

Edited by kulatong
Link to comment
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!

Register a new account

Sign in

Already have an account? Sign in here.

Sign In Now
×
×
  • Create New...