Switch-Toolbox/PhyreEngine_PTexture2D_phyre.bms
2019-05-18 18:24:45 -04:00

1178 lines
No EOL
42 KiB
Text

set DEBUGLEVEL 0
#--------
# GENERAL
# keep import path and filename
# unused
# set KeepImportName True
#--------
# force output DX10 FOURCC DDS file
# doesn't work with LA88, as there is no analog in DXGI
# warns and falls back to regular DDS file
set DX10DDS False
#--------
# GCM/GNM
# "RAW" - outputs only data without headers
# adds info to the filename
# for manual processing with id-daemon's "Raw texture previewer/converter" GUI
# https://zenhax.com/viewtopic.php?f=7&t=7099
# will add automatic batch file creation
# if id-daemon adds swizzle options to his/her CLI version of the tool
# "GNF" - outputs a GNF file
# "DDS" - outputs a DDS file
set GCMOutputMode "DDS" # "RAW" or "DDS"
set GNMOutputMode "DDS" # "RAW", "GNF" or "DDS"
# Data offset for GNF files
# 0x30 - for compability with Noesis
# 0x100 - with Scarlet: https://github.com/xdanieldzd/Scarlet
set GNFDataOffset 0x30
#-------------------------------------------------------------------------------
endian big
idstring 0 "PHYR"
endian save FileEndian
goto 0 0
set i 0
for FileOffset = 0 != ""
if FileEndian == 0
findloc FileOffset string "RYHP" 0 ""
elif FileEndian == 1
findloc FileOffset string "PHYR" 0 ""
endif
if FileOffset == ""
print "[i] Total PhyreEngine asset markers found: %i%."
else
math i += 1
putarray 40 i FileOffset
goto FileOffset 0
goto 1 0 SEEK_CUR
endif
next
for j = 1 <= i
getarray FileOffset 40 j
if j < i
xmath TMP "j+1"
getarray FileOffset_next 40 TMP
else
get FileOffset_next asize
endif
xmath ScanSize "FileOffset_next-FileOffset"
print "[i] PhyreEngine asset marker #%j%. Data start: %FileOffset|h%; data to scan: %ScanSize% B."
log MEMORY_FILE5 FileOffset ScanSize 0
CallFunction MainProcess 0 -5
next j
#-------------------------------------------------------------------------------
StartFunction MainProcess
# MainProcess_ARG1 - file number
endian big
idstring MainProcess_ARG1 "PHYR"
get PClusterHeaderBase_m_size long MainProcess_ARG1 # PClusterHeaderBase.m_size
get m_packedNamespaceSize long MainProcess_ARG1
get m_platformID long MainProcess_ARG1
if m_platformID == 0x44583131
set m_platformID "DX11"
elif m_platformID == 0x47434D00
set m_platformID "GCM"
elif m_platformID == 0x47584D01
set m_platformID "GXM"
elif m_platformID == 0x474E4D02
set m_platformID "GNM"
else
print "[x] Unsupported platform: %m_platformID|h%!"
cleanexit
endif
print "[i] Platform: %m_platformID%"
get DUMMY long MainProcess_ARG1 # m_instanceListCount
get DUMMY long MainProcess_ARG1 # m_arrayFixupSize
get m_arrayFixupCount long MainProcess_ARG1
print "[i] # of textures: %m_arrayFixupCount%"
# --- PClusterHeaderBase end
goto PClusterHeaderBase_m_size MainProcess_ARG1
get MAGIC2 long MainProcess_ARG1
if MAGIC2 != 0x01020304
print "[x] Wrong magic #2: %MAGIC|h%"
cleanexit
endif
get m_packedNamespaceSize long MainProcess_ARG1
get SKIPTHESE long MainProcess_ARG1
get ROOTDESCRIPTORS long MainProcess_ARG1
get SUBDESCRIPTORS long MainProcess_ARG1
get STRING_TABLE_SIZE long MainProcess_ARG1
math SKIPTHESE += 2
for i = 0 < SKIPTHESE
get DUMMY long MainProcess_ARG1
next i
if DEBUGLEVEL >= 2
print "#-#| DUMMY0 | FLAGS1 | DUMMY1 |DESC_STR_O|SUB|F|L| DUMMY2 | DUMMY3 | DUMMY4 | DUMMY5 | DUMMY6 |NAME"
print "---+----------+----------+----------+----------+---+-+-+----------+----------+----------+----------+----------+----"
endif
set j_min 0
set j_max 0
for i = 1 <= ROOTDESCRIPTORS
get DUMMY0 long MainProcess_ARG1
get DUMMY1 short MainProcess_ARG1
get DUMMY2 short MainProcess_ARG1
get DESC_STRING_OFFSET long MainProcess_ARG1
get SUBRECORDS long MainProcess_ARG1
get DUMMY3 long MainProcess_ARG1
get DUMMY4 long MainProcess_ARG1
get DUMMY5 long MainProcess_ARG1
get DUMMY6 long MainProcess_ARG1
get DUMMY7 long MainProcess_ARG1
if SUBRECORDS > 0
math FirstSubrecord = j_max
math FirstSubrecord += 1
math j_max += SUBRECORDS
math LastSubrecord = j_max
else
math FirstSubrecord = 0
math LastSubrecord = 0
endif
savepos CurrentOffset MainProcess_ARG1
xmath NAME_OFF "PClusterHeaderBase_m_size+m_packedNamespaceSize-STRING_TABLE_SIZE+DESC_STRING_OFFSET"
goto NAME_OFF MainProcess_ARG1
get NAME string MainProcess_ARG1
goto CurrentOffset MainProcess_ARG1
putarray 0 i SUBRECORDS
putarray 1 i FirstSubrecord
putarray 2 i LastSubrecord
putarray 3 i NAME
if DEBUGLEVEL >= 2
print "%i%-0|%DUMMY0|h%|%DUMMY1|h%|%DUMMY2|h%|%DESC_STRING_OFFSET|h%|%SUBRECORDS%|%FirstSubrecord%|%LastSubrecord%|%DUMMY3|h%|%DUMMY4|h%|%DUMMY5|h%|%DUMMY6|h%|%DUMMY7|h%|%NAME%"
endif
next i
if DEBUGLEVEL >= 2
print "----+----------+----------+----------+----------+---+-+-+----------+----------+----------+----------+----------+----"
endif
if DEBUGLEVEL >= 2
print "#|DESC_STR_O| DUMMY1 | OFFSET | DATASIZE | DUMMY4 | DUMMY5 |NAME"
print "-+----------+----------+----------+----------+----------+----------+----"
# 0|0x00000163|0x0000000e|0x00000018|0x00000004|0x00000010|0x00000000|m_id
endif
for i = 1 <= SUBDESCRIPTORS
get DESC_STRING_OFFSET long MainProcess_ARG1
get DUMMY1 long MainProcess_ARG1
get OFFSET long MainProcess_ARG1
get SIZE long MainProcess_ARG1
get DUMMY4 long MainProcess_ARG1
get DUMMY5 long MainProcess_ARG1
savepos CurrentOffset MainProcess_ARG1
xmath NAME_OFF "PClusterHeaderBase_m_size+m_packedNamespaceSize-STRING_TABLE_SIZE+DESC_STRING_OFFSET"
goto NAME_OFF MainProcess_ARG1
get NAME string MainProcess_ARG1
# --- safeguard #2; against models and shaders
if NAME == "PEffect"
print "[x] Not a texture!"
cleanexit
endif
# --- safeguard end
goto CurrentOffset MainProcess_ARG1
putarray 4 i OFFSET
putarray 5 i SIZE
putarray 6 i NAME
if DEBUGLEVEL >= 2
print "%i%|%DESC_STRING_OFFSET|h%|%DUMMY1|h%|%OFFSET|h%|%SIZE|h%|%DUMMY4|h%|%DUMMY5|h%|%NAME%"
endif
next i
if DEBUGLEVEL >= 2
print "--+----------+----------+----------+----------+----------+----------+----"
endif
set PInstanceListHeader_SIZE 0x24 # size of one PInstanceListHeader structure
for i = 1 <= ROOTDESCRIPTORS
getarray SUBRECORDS 0 i
getarray FirstSubrecord 1 i
getarray LastSubrecord 2 i
getarray ROOTNAME 3 i
if DEBUGLEVEL >= 2
print "%i%-0|%ROOTNAME%"
endif
if SUBRECORDS > 0
for j = FirstSubrecord <= LastSubrecord
getarray OFFSET 4 j
getarray SIZE 5 j
getarray NAME 6 j
if i >= 2 && i <= 6
math BaseOffset = OFFSET
goto BaseOffset MainProcess_ARG1
get TMP long MainProcess_ARG1
goto BaseOffset MainProcess_ARG1
getdstring TMP2 4 MainProcess_ARG1
if NAME == "m_maxTextureBufferSize" # DX11 (PC)
math DataSize = TMP
elif NAME == "m_vramBufferSize" # GCM (PS3)
math DataSize = TMP
elif NAME == "m_cdramTextureBufferSize" # GXM (PSVita)
math DataSize = TMP
elif NAME == "m_sharedVideoMemoryBufferSize" # GNM (PS4)
math DataSize = TMP
elif NAME == "m_instanceListCount" # how many PInstanceListHeader structs are there
math m_instanceListCount_ = TMP
elif NAME == "m_totalDataSize"
math m_totalDataSize_ = TMP
elif NAME == "m_userFixupCount"
math m_userFixupCount_ = TMP
elif NAME == "m_userFixupDataSize"
math m_userFixupDataSize_ = TMP
elif NAME == "m_arrayFixupSize"
math m_arrayFixupSize_ = TMP
elif NAME == "m_pointerFixupSize"
math m_pointerFixupSize_ = TMP
endif
if DEBUGLEVEL >= 2
print "%i%-%j%|%OFFSET|h%|%SIZE|h%|%NAME% = %TMP|h%|%TMP%|%TMP2% @ %BaseOffset|h%"
endif
elif ROOTNAME == "PInstanceListHeader"
for k = 1 <= m_instanceListCount_
xmath BaseOffset "OFFSET+PClusterHeaderBase_m_size+m_packedNamespaceSize+PInstanceListHeader_SIZE*(k-1)"
goto BaseOffset MainProcess_ARG1
get TMP long MainProcess_ARG1
if NAME == "m_size"
putarray 7 k TMP
elif NAME == "m_objectsSize"
putarray 8 k TMP
elif NAME == "m_arraysSize"
putarray 9 k TMP
endif
if DEBUGLEVEL >= 2
print "%i%-%j%|%OFFSET|h%|%SIZE|h%|%NAME%[%k%] = %TMP|h%|%TMP% @ %BaseOffset|h%"
endif
next k
elif ROOTNAME == "PString"
xmath BaseOffset "PClusterHeaderBase_m_size+m_packedNamespaceSize+PInstanceListHeader_SIZE*m_instanceListCount_"
getarray TMP 8 1
math BaseOffset += TMP
goto BaseOffset MainProcess_ARG1
getarray TMP 9 1
log MEMORY_FILE4 BaseOffset TMP MainProcess_ARG1
if DEBUGLEVEL >= 2
print "%i%-%j%|%OFFSET|h%|%SIZE|h%|%NAME% = %TMP% @ %BaseOffset|h%"
endif
elif ROOTNAME == "PTexture2DBase" && m_platformID != "GCM"
xmath BaseOffset "OFFSET+PClusterHeaderBase_m_size+m_packedNamespaceSize+PInstanceListHeader_SIZE*m_instanceListCount_"
getarray TMP 7 1
math BaseOffset += TMP
goto BaseOffset MainProcess_ARG1
get TMP long MainProcess_ARG1
if NAME == "m_width"
math m_width_ = TMP
elif NAME == "m_height"
math m_height_ = TMP
endif
if DEBUGLEVEL >= 2
print "%i%-%j%|%OFFSET|h%|%SIZE|h%|%NAME% = %TMP|h%|%TMP% @ %BaseOffset|h%"
endif
elif ROOTNAME == "PTexture2DGCM"
for k = 1 <= m_arrayFixupCount
for l = 1 <= SUBDESCRIPTORS
getarray NAME 6 l
if NAME == "m_samplerState"
math m_samplerState_PROPNO = l
elif NAME == "m_width"
math m_width_PROPNO = l
elif NAME == "m_height"
math m_height_PROPNO = l
elif NAME == "m_buffers"
math m_buffers_PROPNO = l
elif NAME == "m_u"
math m_u_PROPNO = l
elif NAME == "m_gcmTextureBlock"
math m_gcmTextureBlock_PROPNO = l
elif NAME == "m_offsetInAllocatedBuffer"
math m_offsetInAllocatedBuffer_PROPNO = l
endif
next l
getarray TMP 4 m_samplerState_PROPNO
getarray TMP2 5 m_samplerState_PROPNO
xmath PTextureSamplerStateGCM_SIZE "TMP+TMP2"
xmath BaseOffset "PClusterHeaderBase_m_size+m_packedNamespaceSize+PInstanceListHeader_SIZE*m_instanceListCount_+PTextureSamplerStateGCM_SIZE*(k-1)"
getarray TMP 7 1
math BaseOffset += TMP
getarray TMP 4 m_width_PROPNO
xmath TempOffset "BaseOffset+TMP"
goto TempOffset MainProcess_ARG1
get m_width_ long MainProcess_ARG1
putarray 11 k m_width_
getarray TMP 4 m_height_PROPNO
xmath TempOffset "BaseOffset+TMP"
goto TempOffset MainProcess_ARG1
get m_height_ long MainProcess_ARG1
putarray 12 k m_height_
getarray TMP 4 m_samplerState_PROPNO
math BaseOffset += TMP
getarray TMP 4 m_buffers_PROPNO
math BaseOffset += TMP
getarray TMP 4 m_u_PROPNO
math BaseOffset += TMP
getarray TMP 4 m_gcmTextureBlock_PROPNO
xmath TempOffset "BaseOffset+TMP"
goto TempOffset MainProcess_ARG1
get format byte MainProcess_ARG1
putarray 13 k format
getarray TMP 4 m_offsetInAllocatedBuffer_PROPNO
xmath TempOffset "BaseOffset+TMP"
goto TempOffset MainProcess_ARG1
get m_offsetInAllocatedBuffer_ long MainProcess_ARG1
putarray 14 k m_offsetInAllocatedBuffer_
next k
else
if DEBUGLEVEL >= 2
print "%i%-%j%|%OFFSET|h%|%SIZE|h%|%NAME%"
endif
endif
next j
endif
next i
xmath BaseOffset "PClusterHeaderBase_m_size+m_packedNamespaceSize+PInstanceListHeader_SIZE*m_instanceListCount_+m_totalDataSize_"
goto BaseOffset MainProcess_ARG1
for i = 1 <= m_userFixupCount_
getct TMP string 0x00 MainProcess_ARG1
putarray 15 i TMP
next i
xmath DataOffset "BaseOffset+m_userFixupDataSize_+(m_userFixupCount_*12)+m_arrayFixupSize_+m_pointerFixupSize_"
# --- safeguard #3; against anything else but supported stuff
getarray TMP 15 1
if TMP == "PTexture2D"
print "[i] PTexture2D"
elif TMP == "PFsBin"
print "[i] PFsBin"
print "[i] Do nothing."
else
print "[x] %TMP% is not supported!"
cleanexit
endif
# --- safeguard end
if TMP == "PTexture2D" # !!!!! UNINDENTED BLOCK
# --- asset name array processing start
xmath BaseOffset "PClusterHeaderBase_m_size+m_packedNamespaceSize+PInstanceListHeader_SIZE*m_instanceListCount_+m_totalDataSize_+m_userFixupDataSize_+(m_userFixupCount_*12)+m_pointerFixupSize_"
goto BaseOffset MainProcess_ARG1
math m_arrayFixupCount_TEMP = m_arrayFixupCount
math m_arrayFixupCount_TEMP += 2
for i = 1 <= m_arrayFixupCount_TEMP
get TMP byte MainProcess_ARG1
set threshold 0x80
for TMP = TMP >= threshold
get TMP2 byte MainProcess_ARG1
xmath TMP "TMP+(TMP2-1)*threshold"
math threshold *= 0x80
next
putarray 50 i TMP
next i
savepos CurrentOffset MainProcess_ARG1
math TMP = CurrentOffset
math TMP -= BaseOffset
if TMP != m_arrayFixupSize_
print "[!] m_arrayFixupSize (%m_arrayFixupSize_%) mismatch with length of read data (%TMP%)!"
endif
getarray TMP 50 1
getarray TMP2 50 2
if TMP == 8 && TMP2 & 1
for i = 1 <= m_arrayFixupCount
math j = i
math j += 2
getarray TMP 50 j
putarray 50 i TMP
next i
else
print "[!] List_AssetNameArrayOffset: unexpected value!"
endif
for i = 1 <= m_arrayFixupCount
getarray TMP 50 i
goto TMP MEMORY_FILE4
getct TMP string 0x00 MEMORY_FILE4
putarray 10 i TMP
next i
# --- asset name array processing end
getarray FORMAT_TYPE 15 2
if m_platformID != "GCM"
getarray TMP 10 1
print "[i] Asset import name: %TMP%"
print "[i] Format: %FORMAT_TYPE%; WxH: %m_width_%x%m_height_%; data start: %DataOffset|h%; data size: %DataSize% B."
endif
#-------------------------------------------------------------------------------
if m_platformID == "DX11"
CallFunction GetFormatParameters 1
CallFunction IgnoreMipMaps 1
CallFunction CreateDDSHeader
append
log MEMORY_FILE DataOffset DataSize MainProcess_ARG1
append
getarray NAME 10 1
CallFunction RemoveExtensionFromAssetImportName 1
string NAME += ".dds"
# get PREALLOC asize MEMORY_FILE
log NAME 0 PREALLOC MEMORY_FILE
#-------------------------------------------------------------------------------
elif m_platformID == "GCM"
for i = 1 <= m_arrayFixupCount
math GCMDataOffset = DataOffset
getarray TMP 14 i
math GCMDataOffset += TMP
if i < m_arrayFixupCount
getarray TMP 14 i
math DUMMY = i
math DUMMY += 1
getarray TMP2 14 DUMMY
xmath GCMDataSize "TMP2-TMP"
else
getarray TMP 14 i
xmath GCMDataSize "DataSize-TMP"
endif
getarray NAME 10 i
print "[i] Texture #%i%. Asset import name: %NAME%"
getarray m_width_ 11 i
getarray m_height_ 12 i
# --- consolidated texture decoding parameters start
set IsSwizzled True
getarray format 13 i
if format && 0x80
math format_L = format
math format_L &= 0xF
if format_L == 1
set FORMAT_TYPE "L8"
elif format_L == 2
set FORMAT_TYPE "ARGB1555"
elif format_L == 3
set FORMAT_TYPE "ARGB4444"
elif format_L == 5 # possible race condition resolves to "RGBA8"
for j = 2 <= m_userFixupCount_
getarray m_userFixupData 15 j
if m_userFixupData == "RGBA8"
set FORMAT_TYPE "RGBA8"
elif m_userFixupData == "ARGB8"
set FORMAT_TYPE "ARGB8"
endif
next j
elif format_L == 6
set FORMAT_TYPE "DXT1"
elif format_L == 7
set FORMAT_TYPE "DXT3"
elif format_L == 8
set FORMAT_TYPE "DXT5"
elif format_L == 11
set FORMAT_TYPE "LA88"
else
print "[x] Texture #%i%. Unhandled format: %format|h% = %FORMAT_TYPE%; swizzled: %IsSwizzled%; WxH: %m_width_%x%m_height_%; data start: %GCMDataOffset|h%; data size: %GCMDataSize% B."
cleanexit
endif
CallFunction GetFormatParameters 1
if IsBlockCompressed == 1
set IsSwizzled False
endif
if format && 0x20
set IsSwizzled False
endif
else
print "[x] format && 0x80 hasn't pass!"
cleanexit
endif
# --- consolidated texture decoding parameters end
print "[i] Texture #%i%. Format: %format|h% = %FORMAT_TYPE%; swizzled: %IsSwizzled%; WxH: %m_width_%x%m_height_%; data start: %GCMDataOffset|h%; data size: %GCMDataSize% B."
CallFunction IgnoreMipMaps 1
if GCMOutputMode == "RAW"
CallFunction GetFormatParameters 1
if FORMAT_TYPE == "ARGB1555" || FORMAT_TYPE == "ARGB4444"
log MEMORY_FILE GCMDataOffset GCMDataSize MainProcess_ARG1
set CurrentOffset 0
goto CurrentOffset MEMORY_FILE
for CurrentOffset = CurrentOffset < GCMDataSize
getvarchr TMP MEMORY_FILE CurrentOffset short
math TMP s= BytesPerBlock # 2
putvarchr MEMORY_FILE CurrentOffset TMP short
next CurrentOffset += BytesPerBlock # 2
endif
getarray NAME 10 1
CallFunction RemoveExtensionFromAssetImportName 1
string TMP P= "-PS3_%DXGI%_(%TextDXGI%)_0_%m_width_%_%m_height_%"
string NAME += TMP
if FORMAT_TYPE == "ARGB1555" || FORMAT_TYPE == "ARGB4444"
log NAME 0 GCMDataSize MEMORY_FILE
else
log NAME GCMDataOffset GCMDataSize MainProcess_ARG1
endif
elif GCMOutputMode == "DDS"
CallFunction CreateDDSHeader
append
log MEMORY_FILE GCMDataOffset GCMDataSize MainProcess_ARG1
append
# Morton order unswizzling start
if IsSwizzled == True
log MEMORY_FILE2 GCMDataOffset GCMDataSize MainProcess_ARG1
xmath WidthInBlocks m_width_
xmath HeightInBlocks m_height_
xmath RowSize "BytesPerBlock*WidthInBlocks"
xmath BlocksSwizzled "WidthInBlocks*HeightInBlocks"
if WidthInBlocks < HeightInBlocks
math min = WidthInBlocks
else
math min = HeightInBlocks
endif
# finding log(min, 2)
math min_log2 = 31
set min2 long min
set check 0
for check = check != 0x80000000
math min2 <<= 1
math min_log2 -= 1
math check = min2
math check &= 0x80000000
next
math min_mask = min
math min_mask -= 1
for Z = 0 < BlocksSwizzled
math X = Z
math X &= 0x55555555
xmath X "(X ^ (X >> 1)) & 0x33333333"
xmath X "(X ^ (X >> 2)) & 0x0f0f0f0f"
xmath X "(X ^ (X >> 4)) & 0x00ff00ff"
xmath X "(X ^ (X >> 8)) & 0x0000ffff"
math Y = Z
math Y >>= 1
math Y &= 0x55555555
xmath Y "(Y ^ (Y >> 1)) & 0x33333333"
xmath Y "(Y ^ (Y >> 2)) & 0x0f0f0f0f"
xmath Y "(Y ^ (Y >> 4)) & 0x00ff00ff"
xmath Y "(Y ^ (Y >> 8)) & 0x0000ffff"
# adapted from https://github.com/xdanieldzd/GXTConvert/blob/master/GXTConvert/Conversion/PostProcessing.cs
if HeightInBlocks < WidthInBlocks
math TMP = Z
math TMP >>= min_log2
math TMP >>= min_log2
math TMP <<= min_log2
math TMP <<= min_log2
math TMP2 = X
math TMP2 &= min_mask
math TMP2 <<= min_log2
math TMP |= TMP2
math TMP2 = Y
math TMP2 &= min_mask
math TMP |= TMP2
math X = TMP
math X /= HeightInBlocks
math Y = TMP
math Y %= HeightInBlocks
elif WidthInBlocks < HeightInBlocks
math TMP = Z
math TMP >>= min_log2
math TMP >>= min_log2
math TMP <<= min_log2
math TMP <<= min_log2
math TMP2 = Y
math TMP2 &= min_mask
math TMP2 <<= min_log2
math TMP |= TMP2
math TMP2 = X
math TMP2 &= min_mask
math TMP |= TMP2
math X = TMP
math X %= WidthInBlocks
math Y = TMP
math Y /= WidthInBlocks
endif
# adaptation end
math PixelOffset_In = Z
math PixelOffset_In *= BytesPerBlock
# math PixelOffset_In += 0
math PixelOffset_Out = DDSHeaderSize
math TMP = X
math TMP *= BytesPerBlock
math PixelOffset_Out += TMP
math TMP = Y
math TMP *= RowSize
math PixelOffset_Out += TMP
goto PixelOffset_In MEMORY_FILE2
goto PixelOffset_Out MEMORY_FILE
for o = 0 < BytesPerBlock
get TMP byte MEMORY_FILE2
put TMP byte MEMORY_FILE
next o
next Z
endif
# Morton order unswizzling end
get PREALLOC asize MEMORY_FILE
if FORMAT_TYPE == "ARGB1555" || FORMAT_TYPE == "ARGB4444"
set CurrentOffset DDSHeaderSize
goto CurrentOffset MEMORY_FILE
for CurrentOffset = CurrentOffset < PREALLOC
getvarchr TMP MEMORY_FILE CurrentOffset short
math TMP s= BytesPerBlock # 2
putvarchr MEMORY_FILE CurrentOffset TMP short
next CurrentOffset += BytesPerBlock # 2
endif
getarray NAME 10 i
CallFunction RemoveExtensionFromAssetImportName 1
string NAME += ".dds"
log NAME 0 PREALLOC MEMORY_FILE
else
print "[x] Please specify correct GCMOutputMode (currently %GCMOutputMode%)!"
cleanexit
endif
next i
#-------------------------------------------------------------------------------
elif m_platformID == "GXM"
getarray NAME 10 1
CallFunction RemoveExtensionFromAssetImportName 1
string NAME += ".gxt"
log NAME DataOffset DataSize 0
#-------------------------------------------------------------------------------
elif m_platformID == "GNM"
if GNMOutputMode = "RAW"
CallFunction GetFormatParameters 1
getarray NAME 10 1
CallFunction RemoveExtensionFromAssetImportName 1
string TMP P= "-PS4_%DXGI%_(%TextDXGI%)_0_%m_width_%_%m_height_%"
string NAME += TMP
log NAME DataOffset DataSize MainProcess_ARG1
elif GNMOutputMode = "GNF"
for i = 1 <= SUBDESCRIPTORS
getarray NAME 6 i
if NAME == "m_texState"
math m_texState_PROPNO = i
elif NAME == "m_buffers"
math m_buffers_PROPNO = i
elif NAME == "m_u"
math m_u_PROPNO = i
elif NAME == "m_gnmTexture"
math m_gnmTexture_PROPNO = i
endif
next i
xmath BaseOffset "PClusterHeaderBase_m_size+m_packedNamespaceSize+PInstanceListHeader_SIZE*m_instanceListCount_"
getarray TMP 7 1
math BaseOffset += TMP
getarray TMP 4 m_texState_PROPNO
math BaseOffset += TMP
getarray TMP 4 m_buffers_PROPNO
math BaseOffset += TMP
getarray TMP 4 m_u_PROPNO
math BaseOffset += TMP
getarray TMP 4 m_gnmTexture_PROPNO
math BaseOffset += TMP
set MEMORY_FILE binary "\x47\x4E\x46\x20\x28\x00\x00\x00\x02\x01\x00\x00\x00\x00\x00\x00"
getarray TMP 5 m_gnmTexture_PROPNO
append
log MEMORY_FILE BaseOffset TMP MainProcess_ARG1
append
math GNFSize = DataSize
math GNFSize += GNFDataOffset
math TMP = GNFDataOffset
math TMP -= 1
putvarchr MEMORY_FILE TMP 0
putvarchr MEMORY_FILE 0xC GNFSize long
putvarchr MEMORY_FILE 0x2C DataSize long
# adaptation of https://github.com/xdanieldzd/Scarlet/blob/master/Scarlet.IO.ImageFormats/GNF.cs
getvarchr TMP MEMORY_FILE 0x14 long
math SH1 = 25
math SH2 = 20
xmath dataFormat "TMP < (31-SH1) > (31-SH1+SH2)"
math SH1 = 29
math SH2 = 26
xmath numFormat "TMP < (31-SH1) > (31-SH1+SH2)"
getvarchr TMP MEMORY_FILE 0x18 long
math SH1 = 13
math SH2 = 0
xmath width "TMP < (31-SH1) > (31-SH1+SH2) + 1"
math SH1 = 27
math SH2 = 14
xmath height "TMP < (31-SH1) > (31-SH1+SH2) + 1"
getvarchr TMP MEMORY_FILE 0x20 long
math SH1 = 12
math SH2 = 0
xmath depth "TMP < (31-SH1) > (31-SH1+SH2)"
math SH1 = 26
math SH2 = 13
xmath pitch "TMP < (31-SH1) > (31-SH1+SH2) + 1"
getvarchr TMP MEMORY_FILE 0x1C long
math SH1 = 2
math SH2 = 0
xmath destX "TMP < (31-SH1) > (31-SH1+SH2)"
math SH1 = 5
math SH2 = 3
xmath destY "TMP < (31-SH1) > (31-SH1+SH2)"
math SH1 = 8
math SH2 = 6
xmath destZ "TMP < (31-SH1) > (31-SH1+SH2)"
math SH1 = 11
math SH2 = 9
xmath destW "TMP < (31-SH1) > (31-SH1+SH2)"
if DEBUGLEVEL >= 3
print "[i] GNF parameters:"
print "[i] dataFormat: %dataFormat|h%"
print "[i] numFormat: %numFormat|h%"
print "[i] width: %width%"
print "[i] height: %height%"
print "[i] depth: %depth%"
print "[i] pitch: %pitch%"
print "[i] destX: %destX%"
print "[i] destY: %destY%"
print "[i] destZ: %destZ%"
print "[i] destW: %destW%"
print "[i] End of GNF parameters."
endif
append
log MEMORY_FILE DataOffset DataSize MainProcess_ARG1
append
getarray NAME 10 1
CallFunction RemoveExtensionFromAssetImportName 1
string NAME += ".gnf"
log NAME 0 GNFSize MEMORY_FILE
elif GNMOutputMode = "DDS"
# Peano curve(?) unswizzling start
CallFunction GetFormatParameters 1
log MEMORY_FILE2 DataOffset DataSize MainProcess_ARG1
putvarchr MEMORY_FILE PREALLOC 0
# adaptation of https://github.com/xdanieldzd/Scarlet/blob/8c56632eb2968e64b6d6fad14af3758e606a127d/Scarlet/Drawing/ImageBinary.cs#L1256
set MEMORY_FILE4 binary "\x00\x01\x08\x09\x02\x03\x0A\x0B\x10\x11\x18\x19\x12\x13\x1A\x1B\x04\x05\x0C\x0D\x06\x07\x0E\x0F\x14\x15\x1C\x1D\x16\x17\x1E\x1F\x20\x21\x28\x29\x22\x23\x2A\x2B\x30\x31\x38\x39\x32\x33\x3A\x3B\x24\x25\x2C\x2D\x26\x27\x2E\x2F\x34\x35\x3C\x3D\x36\x37\x3E\x3F"
math tileWidth = 8
math tileHeight = 8
xmath tileSize "tileWidth * tileHeight"
math WidthInBlocks = m_width_
math HeightInBlocks = m_height_
if IsBlockCompressed == 1
math WidthInBlocks u>>= 2
math HeightInBlocks u>>= 2
endif
/*
# requires reading pitch from GNF parameters
if WidthInBlocks % tileWidth
print "[!] Physical width doesn't match with virtual!"
math m_width_ = pitch
print "[!] Physical width: %m_width_%"
endif
*/
if WidthInBlocks % tileWidth || HeightInBlocks % tileHeight
print "[!] Physical dimensions don't match with virtual!"
math WidthVirtual = m_width_
math HeightVirtual = m_height_
xmath WidthPhysical "((WidthInBlocks + (tileWidth-1)) / tileWidth) * tileWidth"
xmath HeightPhysical "((HeightInBlocks + (tileHeight-1)) / tileHeight) * tileHeight"
if IsBlockCompressed == 1
math WidthPhysical u<<= 2
math HeightPhysical u<<= 2
endif
print "[!] Physical dimensions: %WidthPhysical%x%HeightPhysical%"
math m_width_ = WidthPhysical
math m_height_ = HeightPhysical
else
math WidthVirtual = m_width_
math HeightVirtual = m_height_
math WidthPhysical = m_width_
math HeightPhysical = m_height_
endif
CallFunction IgnoreMipMaps 1
CallFunction GetFormatParameters 1
CallFunction CreateDDSHeader
math WidthInBlocks = m_width_
math HeightInBlocks = m_height_
if IsBlockCompressed == 1
math WidthInBlocks u>>= 2
math HeightInBlocks u>>= 2
endif
xmath RowSize "BytesPerBlock*WidthInBlocks"
for InY = 0 < HeightInBlocks
for InX = 0 < WidthInBlocks
math Z = InY
math Z *= WidthInBlocks
math Z += InX
xmath globalX "(Z / tileSize) * tileWidth"
xmath globalY "(globalX / WidthInBlocks) * tileHeight"
math globalX %= WidthInBlocks
xmath inTileX "Z % tileWidth"
xmath inTileY "(Z / tileWidth) % tileHeight"
xmath inTilePixel "(inTileY * tileHeight) + inTileX"
getvarchr inTilePixel MEMORY_FILE4 inTilePixel byte
xmath inTileX "inTilePixel % tileWidth"
xmath inTileY "inTilePixel / tileHeight"
xmath OutX "globalX + inTileX"
xmath OutY "globalY + inTileY"
math PixelOffset_In = 0
math TMP = InX
math TMP *= BytesPerBlock
math PixelOffset_In += TMP
math TMP = InY
math TMP *= RowSize
math PixelOffset_In += TMP
math PixelOffset_Out = DDSHeaderSize
math TMP = OutX
math TMP *= BytesPerBlock
math PixelOffset_Out += TMP
math TMP = OutY
math TMP *= RowSize
math PixelOffset_Out += TMP
for o = 0 < BytesPerBlock
getvarchr TMP MEMORY_FILE2 PixelOffset_In byte
math PixelOffset_In += 1
putvarchr MEMORY_FILE PixelOffset_Out TMP byte
math PixelOffset_Out += 1
next o
next InX
next InY
# Peano curve(?) unswizzling end
if WidthVirtual != WidthPhysical || HeightVirtual != HeightPhysical
print "[!] Cropping %WidthPhysical%x%HeightPhysical% -> %WidthVirtual%x%HeightVirtual%"
log MEMORY_FILE2 DDSHeaderSize DataSize MEMORY_FILE
math m_width_ = WidthVirtual
math m_height_ = HeightVirtual
CallFunction GetFormatParameters 1
CallFunction IgnoreMipMaps 1
CallFunction GetFormatParameters 1
CallFunction CreateDDSHeader
math WidthVirtualInBlocks = WidthVirtual
math WidthPhysicalInBlocks = WidthPhysical
math HeightVirtualInBlocks = HeightVirtual
math HeightPhysicalInBlocks = HeightPhysical
if IsBlockCompressed == 1
math WidthVirtualInBlocks u>>= 2
math WidthPhysicalInBlocks u>>= 2
math HeightVirtualInBlocks u>>= 2
math HeightPhysicalInBlocks u>>= 2
endif
goto DDSHeaderSize MEMORY_FILE
xmath ReadInOneRow "BytesPerBlock*WidthVirtualInBlocks"
xmath SkipInOneRow "RowSize - ReadInOneRow"
for Y = 0 < HeightVirtualInBlocks
xmath Offset_IN "Y * RowSize"
goto Offset_IN MEMORY_FILE2
append
log MEMORY_FILE Offset_IN ReadInOneRow MEMORY_FILE2
append
goto SkipInOneRow MEMORY_FILE2 SEEK_CUR
next Y
endif
getarray NAME 10 1
CallFunction RemoveExtensionFromAssetImportName 1
string NAME += ".dds"
log NAME 0 PREALLOC MEMORY_FILE
else
print "[x] Please specify correct GNMOutputMode (currently %GNMOutputMode%)!"
cleanexit
endif
endif
endif # !!!!!
EndFunction # !!!!!
#-------------------------------------------------------------------------------
StartFunction CreateDDSHeader
CallFunction GetFormatParameters 1
set DXT 0
if FORMAT_TYPE == "RGBA8"
set dwFlags 0x41 # set DDPF_RGB (0x40), DDPF_ALPHAPIXELS (0x1)
set dwRGBBitCount 32
set dwRBitMask 0x000000ff
set dwGBitMask 0x0000ff00
set dwBBitMask 0x00ff0000
set dwABitMask 0xff000000
elif FORMAT_TYPE == "ARGB8"
set dwFlags 0x41 # set DDPF_RGB (0x40), DDPF_ALPHAPIXELS (0x1)
set dwRGBBitCount 32
if m_platformID == "DX11"
set dwRBitMask 0x0000ff00
set dwGBitMask 0x00ff0000
set dwBBitMask 0xff000000
set dwABitMask 0x000000ff
else
set dwRBitMask 0x00ff0000
set dwGBitMask 0x0000ff00
set dwBBitMask 0x000000ff
set dwABitMask 0xff000000
endif
elif FORMAT_TYPE == "ARGB8_SRGB"
set DXGI 90 # 90 = "b8g8r8a8_unorm_srgb"
elif FORMAT_TYPE == "RGBA16F"
set DXGI 10 # 10 = "r16g16b16a16_float"
elif FORMAT_TYPE == "ARGB1555"
set dwFlags 0x41 # set DDPF_RGB (0x40), DDPF_ALPHAPIXELS (0x1)
set dwRGBBitCount 16
set dwRBitMask 0x7c00
set dwGBitMask 0x03e0
set dwBBitMask 0x001f
set dwABitMask 0x8000
elif FORMAT_TYPE == "ARGB4444"
set dwFlags 0x41 # set DDPF_RGB (0x40), DDPF_ALPHAPIXELS (0x1)
set dwRGBBitCount 16
set dwRBitMask 0x0f00
set dwGBitMask 0x00f0
set dwBBitMask 0x000f
set dwABitMask 0xf000
elif FORMAT_TYPE == "LA88"
set dwFlags 0x20001 # set DDPF_LUMINANCE (0x20000), DDPF_ALPHAPIXELS (0x1)
set dwRGBBitCount 16
set dwRBitMask 0x00ff
set dwGBitMask 0
set dwBBitMask 0
set dwABitMask 0xff00
elif FORMAT_TYPE == "L8"
set dwFlags 0x20000 # set DDPF_LUMINANCE (0x20000)
set dwRGBBitCount 8
set dwRBitMask 0xff
set dwGBitMask 0
set dwBBitMask 0
set dwABitMask 0
elif FORMAT_TYPE == "A8"
set dwFlags 1 # set DDPF_ALPHAPIXELS (0x1)
set dwRGBBitCount 8
set dwRBitMask 0
set dwGBitMask 0
set dwBBitMask 0
set dwABitMask 0xff
elif FORMAT_TYPE == "DXT1"
set DXT 0x31545844
elif FORMAT_TYPE == "DXT3"
set DXT 0x33545844
elif FORMAT_TYPE == "DXT5"
set DXT 0x35545844
elif FORMAT_TYPE == "BC5"
set DXT 0x32495441 # "ATI2"
elif FORMAT_TYPE == "BC7"
set DXGI 98 # 98 = "bc7_unorm"
endif
if DX10DDS == True
if DXGI == 0
print "[!] %FORMAT_TYPE% can't be output as DX10 DDS!"
else
set DXT 0x30315844 # "DX10"
print "[i] Forcing DX10 DDS output."
endif
endif
putvarchr MEMORY_FILE PREALLOC 0
log MEMORY_FILE 0 0
set MEMORY_FILE binary "\x44\x44\x53\x20\x7C\x00\x00\x00\x07\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x20\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x10\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00\x00"
endian little
# DDS Header (DDS_HEADER)
putvarchr MEMORY_FILE 0x0C m_height_ long # dwHeight
putvarchr MEMORY_FILE 0x10 m_width_ long # dwWidth
putvarchr MEMORY_FILE 0x14 DataSize long # dwPitchOrLinearSize
# Pixel format struct (ddspf)
if DXT == 0
putvarchr MEMORY_FILE 0x50 dwFlags long # dwFlags
putvarchr MEMORY_FILE 0x54 DXT long # dwFourCC
putvarchr MEMORY_FILE 0x58 dwRGBBitCount long # dwRGBBitCount
putvarchr MEMORY_FILE 0x5C dwRBitMask long # dwRBitMask
putvarchr MEMORY_FILE 0x60 dwGBitMask long # dwGBitMask
putvarchr MEMORY_FILE 0x64 dwBBitMask long # dwBBitMask
putvarchr MEMORY_FILE 0x68 dwABitMask long # dwABitMask
else
putvarchr MEMORY_FILE 0x50 4 long # dwFlags, set DDPF_FOURCC (0x4)
putvarchr MEMORY_FILE 0x54 DXT long # dwFourCC
endif
# DDS Header cont. (DDS_HEADER2) - empty
# DDS_HEADER_DXT10
if DXT == 0x30315844
putvarchr MEMORY_FILE 0x80 DXGI long # dxgiFormat
putvarchr MEMORY_FILE 0x84 3 long MEMORY_FILE # resourceDimension, set DDS_DIMENSION_TEXTURE2D (3)
putvarchr MEMORY_FILE 0x88 0 long MEMORY_FILE # miscFlag
putvarchr MEMORY_FILE 0x8C 1 long MEMORY_FILE # arraySize
putvarchr MEMORY_FILE 0x90 0 long MEMORY_FILE # miscFlags2
endif
EndFunction
#-------------------------------------------------------------------------------
StartFunction IgnoreMipMaps
CallFunction GetFormatParameters 1
if m_platformID == "GCM"
math DataSizeWithoutMipMaps_prev = GCMDataSize
else
math DataSizeWithoutMipMaps_prev = DataSize
endif
if IsBlockCompressed == 0
xmath DataSizeWithoutMipMaps "m_width_ * m_height_ * BytesPerBlock"
else
xmath DataSizeWithoutMipMaps "(m_width_ >> 2) * (m_height_ >> 2) * BytesPerBlock"
endif
if DataSizeWithoutMipMaps != DataSizeWithoutMipMaps_prev
print "[i] Ignoring mipmaps. New data size: %DataSizeWithoutMipMaps% B."
if m_platformID == "GCM"
math GCMDataSize = DataSizeWithoutMipMaps
else
math DataSize = DataSizeWithoutMipMaps
endif
endif
EndFunction
#-------------------------------------------------------------------------------
StartFunction GetFormatParameters
set DXGI 0
set TextDXGI "unknown"
set IsBlockCompressed 0
set DDSHeaderSize 128
if FORMAT_TYPE == "RGBA8"
set DXGI 28
set TextDXGI "r8g8b8a8_unorm"
set BytesPerBlock 4
elif FORMAT_TYPE == "ARGB8"
set DXGI 87
set TextDXGI "b8g8r8a8_unorm"
set BytesPerBlock 4
elif FORMAT_TYPE == "ARGB8_SRGB"
set DX10DDS True
set DXGI 90
set TextDXGI "b8g8r8a8_unorm_srgb"
set BytesPerBlock 4
elif FORMAT_TYPE == "RGBA16F"
set DX10DDS True
set DXGI 10
set TextDXGI "r16g16b16a16_float"
set BytesPerBlock 8
elif FORMAT_TYPE == "ARGB1555"
set DXGI 86
set TextDXGI "b5g5r5a1_unorm"
set BytesPerBlock 2
elif FORMAT_TYPE == "ARGB4444"
set DXGI 115
set TextDXGI "b4g4r4a4_unorm"
set BytesPerBlock 2
elif FORMAT_TYPE == "LA88"
set DXGI 0
set TextDXGI "unknown"
set BytesPerBlock 2
elif FORMAT_TYPE == "L8"
set DXGI 61
set TextDXGI "r8_unorm"
set BytesPerBlock 1
elif FORMAT_TYPE == "A8"
set DXGI 65
set TextDXGI "a8_unorm"
set BytesPerBlock 1
elif FORMAT_TYPE == "DXT1"
set IsBlockCompressed 1
set DXGI 71
set TextDXGI "bc1_unorm"
set BytesPerBlock 8
elif FORMAT_TYPE == "DXT3"
set IsBlockCompressed 1
set DXGI 74
set TextDXGI "bc2_unorm"
set BytesPerBlock 16
elif FORMAT_TYPE == "DXT5"
set IsBlockCompressed 1
set DXGI 77
set TextDXGI "bc3_unorm"
set BytesPerBlock 16
elif FORMAT_TYPE == "BC5"
set IsBlockCompressed 1
set DXGI 83
set TextDXGI "bc5_unorm"
set BytesPerBlock 16
elif FORMAT_TYPE == "BC7"
set IsBlockCompressed 1
set DX10DDS True
set DXGI 98
set TextDXGI "bc7_unorm"
set BytesPerBlock 16
else
print "[x] Unsupported format: %FORMAT_TYPE%!"
cleanexit
endif
if DX10DDS == True && DXGI != 0
set DDSHeaderSize 148
endif
if m_platformID == "GCM"
xmath PREALLOC "GCMDataSize + DDSHeaderSize"
else
xmath PREALLOC "DataSize + DDSHeaderSize"
endif
EndFunction
#-------------------------------------------------------------------------------
StartFunction RemoveExtensionFromAssetImportName
string NAME % ".dds"
string NAME % ".png"
string NAME % ".tga"
string NAME % ".bmp"
EndFunction
#-------------------------------------------------------------------------------