# Unreal Engine 4 - Unreal Tournament 4 (*WindowsNoEditor.pak) (script 0.4.23)
# script for QuickBMS http://quickbms.aluigi.org
math NO_TAIL_INFO = 0 # set it to 1 for archives with corrupt/missing tail information
quickbmsver "0.8.4"
math TOC_FILE = 0
# set your AES_KEY here as text or C string ("\x11\x22...") or umodel hex (0x1122...)
set AES_KEY binary ""
putarray 10 -1 "KIWIKIWIKIWIKIWIKIWIKIWIKIWIKIWI" # first beta of Street Fighter V
putarray 10 -1 "_aS4mfZK8M5s5KWC2Lz2VsFnGKI7azgl" # current version of Street Fighter V
putarray 10 -1 "bR!@nbR0wnc@rychR!$d@nd@v3d3R3kj!mj0$hk3v!nm!ch@3lm!k3s3@nst3v3t!m" # Victory: The Culling
putarray 10 -1 "casd#55@#$%323!$^#b%05sa5W|hhaf4365s52ss51|55m!|{55s^@@36f233|-|0w@%3g8hssDk35/!Nm|_|%ds23%a32d5&23as3%12p|-|y$t3ds562d23fav3c@dyw38#49" # Victory: The Culling
putarray 10 -1 "C8C4847F3B4FA52D4AAD57A52358CDBC" # Injustice 2 (iOS)
putarray 10 -1 "k14z0ZLR8a7jNm49uyBzxXYY9LpTHcehLSNiC3jAkzBsffPuy8YsTa72RLD9KWIn" # Gal*Gun VR
putarray 10 -1 "E7@[dZfoYCW;+YWR;0JK^{9tt:yU0_T&" # Marvel VS Capcom - Infinite
putarray 10 -1 "E1A1F2E4AA066C54BD5090F463EDDF58D01684243672B3CE809FF47FF473B04A" # OverHit
putarray 10 -1 "I0vV6wr0TFbg3m23QuSIwnYC1sI0AIDq" # Fernbus
putarray 10 -1 "y298qjSb115NqQ3Agad30DWn2QYrTI8CT6aP05l2PBV9Qe92S94PdoVCCy06A38L" # Fortnite
putarray 10 -1 "b9uW0RKNY91be8HN3Lemi68j6Xsi2l7fQJYsp5oR4al4C4c9kY5E0l90411l9P3L" # Dragonball FighterZ
putarray 10 -1 "45DD15D6DD2DA50AEB71CE7A5284CF8EA498B2EC3D52B7E336F3EA0071CE44B3"
putarray 10 -1 "MRZpemumg6t2AXExrMQs6TSoZRG+YSABK338oc6F8kTXu4k6QffJgYAzKl65Tk2L"
putarray 10 -1 "0x9D8C9A4A4FA082F213EED604B6E756237181685EEDA82216437617D7AA5231AF"
putarray 10 -1 ""
math AES_KEY_IS_SET = 0
math ALTERNATIVE_MODE = 0
get ARCHIVE_NAME basename
get ARCHIVE_PATH FILEPATH
math VERSION = 0
math CHUNK_OFFSET_ABSOLUTE = -1 # default, enabled
# 1 = HIT
math WORKAROUND = 0
if NO_TAIL_INFO != 0
get OFFSET asize
math ALTERNATIVE_MODE = 1
else
goto -0x2c
savepos MAGIC_OFF
get MAGIC long #idstring "\xe1\x12\x6f\x5a" # 0x5a6f12e1
if MAGIC == 0
goto -0xcc # Fortnite iOS
savepos MAGIC_OFF
get MAGIC long
math WORKAROUND = 3
endif
endian guess MAGIC # 0x5a6f12e1:le, 0xe1126f5a:be
if MAGIC == 0x1233a # HIT game
math WORKAROUND = 1
elif MAGIC == 0x1066a # OverHit
math WORKAROUND = 1
elif MAGIC == 0x13aed # OverHit
math WORKAROUND = 1
elif ARCHIVE_NAME & "OverHit"
math WORKAROUND = 1
elif ARCHIVE_NAME == "0" # HIT
math WORKAROUND = 1
elif ARCHIVE_PATH & "Gears of War 4"
math WORKAROUND = 2
endif
get VERSION long
endian guess VERSION
get OFFSET longlong
get SIZE longlong
getdstring HASH 20
if WORKAROUND == 1
math VERSION = 3
endif
if VERSION >= 3
goto MAGIC_OFF
goto -1 0 SEEK_CUR
get ENCRYPTED byte
if ENCRYPTED != 0
callfunction SET_AES_KEY 1
log MEMORY_FILE10 OFFSET SIZE
encryption "" ""
math TOC_FILE = -10 # MEMORY_FILE10 is -10
endif
endif
goto OFFSET # don't use TOC_FILE
callfunction GET_NAME 1
endif
if ALTERNATIVE_MODE == 0
get FILES long TOC_FILE
else
math FILES = 0x7fffffff
math MAX_OFF = OFFSET
goto 0
set NAME string ""
endif
math CHUNK_SIZE = 0x10000 # just in case...
for i = 0 < FILES
if ALTERNATIVE_MODE == 0
callfunction GET_NAME 1
if NAMESZ == 0 # lame work-around for Conan Exiles
callfunction GET_NAME 1
endif
endif
savepos TMP_OFF TOC_FILE
get OFFSET longlong TOC_FILE
if WORKAROUND == 2
get ZSIZE long TOC_FILE
get SIZE long TOC_FILE
get ZIP byte TOC_FILE
else
get ZSIZE longlong TOC_FILE
get SIZE longlong TOC_FILE
get ZIP long TOC_FILE
endif
if WORKAROUND == 1
getdstring HASH 20 TOC_FILE
elif VERSION <= 1
get TSTAMP longlong TOC_FILE
endif
if WORKAROUND == 2
else
getdstring HASH 20 TOC_FILE
endif
math CHUNKS = 0
math ENCRYPTED = 0
if VERSION >= 3
if ZIP != 0
get CHUNKS long TOC_FILE
for x = 0 < CHUNKS
get CHUNK_OFFSET longlong TOC_FILE
get CHUNK_END_OFFSET longlong TOC_FILE
putarray 0 x CHUNK_OFFSET
putarray 1 x CHUNK_END_OFFSET
next x
endif
if WORKAROUND == 2
else
get ENCRYPTED byte TOC_FILE
endif
get CHUNK_SIZE long TOC_FILE
endif
if WORKAROUND == 1
if ARCHIVE_NAME == "0" # HIT game only!
math ENCRYPTED = 0
endif
endif
if ALTERNATIVE_MODE != 0
savepos TMP_OFF TOC_FILE
math OFFSET + TMP_OFF
endif
#comtype copy # for AES, do not enable or quickbms 0.9.2 will fail
if ZIP == 3 # JoyfunRPG / Faith of Danschant
# DQXI S: For Dragon Quest XI S, this indicates Lizard/LZ5 v2 compression.
comtype lizard
elif ZIP & 1
comtype zlib
elif ZIP & 2
comtype gzip
elif ZIP & 4
comtype snappy
if VERSION >= 6
comtype oodle
endif
if WORKAROUND == 2
comtype lz4
endif
elif ZIP & 0x10
comtype oodle
else
math ZIP = 0
endif
if CHUNKS > 0
log NAME 0 0
append
math TMP_SIZE = SIZE
if CHUNK_OFFSET_ABSOLUTE < 0 && OFFSET != 0
getarray CHUNK_OFFSET 0 0
if CHUNK_OFFSET u< OFFSET
math CHUNK_OFFSET_ABSOLUTE = 0
else
math CHUNK_OFFSET_ABSOLUTE = 1
endif
endif
for x = 0 < CHUNKS
getarray CHUNK_OFFSET 0 x
getarray CHUNK_END_OFFSET 1 x
math CHUNK_ZSIZE = CHUNK_END_OFFSET
math CHUNK_ZSIZE - CHUNK_OFFSET
math CHUNK_XSIZE = CHUNK_ZSIZE
if ENCRYPTED != 0
callfunction SET_AES_KEY 1
math CHUNK_XSIZE x 16
endif
if TMP_SIZE u< CHUNK_SIZE
math CHUNK_SIZE = TMP_SIZE
endif
if CHUNK_OFFSET_ABSOLUTE == 0
math CHUNK_OFFSET + OFFSET
endif
if ZIP == 0
log NAME CHUNK_OFFSET CHUNK_SIZE 0 CHUNK_XSIZE
else
clog NAME CHUNK_OFFSET CHUNK_ZSIZE CHUNK_SIZE 0 CHUNK_XSIZE
endif
math TMP_SIZE - CHUNK_SIZE
next x
append
else
# the file offset points to an entry containing
# the "same" OFFSET ZSIZE SIZE ZIP HASH ZERO fields,
# just an additional backup... so let's skip them
savepos BASE_OFF TOC_FILE
math BASE_OFF - TMP_OFF
math OFFSET + BASE_OFF
math XSIZE = ZSIZE
if ENCRYPTED != 0
callfunction SET_AES_KEY 1
math XSIZE x 16
endif
if ZIP == 0
log NAME OFFSET SIZE 0 XSIZE
else
clog NAME OFFSET ZSIZE SIZE 0 XSIZE
endif
endif
encryption "" ""
if ALTERNATIVE_MODE != 0
math OFFSET + ZSIZE
goto OFFSET
if OFFSET == MAX_OFF
break
endif
if VERSION >= 4
padding 0x800 # necessary for WitchIt
endif
endif
next i
startfunction SET_AES_KEY_ASK
math AES_KEY_IS_SET = 1
print "The archive is encrypted, select the number of the key to use or type yours:"
for z = 0
getarray KEY 10 z
if KEY == ""
break
endif
print "%z%: %KEY%"
next z
print "%z%: press RETURN for no encryption (Lineage 2 Revolution)"
set KEY unknown "???"
strlen TMP KEY
if KEY == ""
math AES_KEY_IS_SET = -1
set AES_KEY string "no key, encryption disabled"
elif TMP <= 2
getarray AES_KEY 10 KEY
if AES_KEY strncmp "0x"
string AES_KEY << 2
string AES_KEY h AES_KEY
endif
elif KEY strncmp "0x"
string KEY << 2
string AES_KEY h KEY
else
set AES_KEY binary KEY
endif
print "KEY: %AES_KEY%"
endfunction
startfunction SET_AES_KEY
if AES_KEY_IS_SET == 0
callfunction SET_AES_KEY_ASK 1
endif
if AES_KEY_IS_SET > 0
encryption aes AES_KEY "" 0 32
endif
endfunction
startfunction GET_NAME
get NAMESZ signed_long TOC_FILE
if NAMESZ >= 0
if NAMESZ > 0x200
math ALTERNATIVE_MODE = 1
else
getdstring NAME NAMESZ TOC_FILE
endif
else
math NAMESZ n NAMESZ
if NAMESZ > 0x200
math ALTERNATIVE_MODE = 1
else
math NAMESZ * 2
getdstring NAME NAMESZ TOC_FILE
set NAME unicode NAME
endif
endif
endfunction