View Single Post
  #1  
Old 10-03-2019, 03:06
Simorq's Avatar
Simorq Simorq is offline
Registered User
 
Join Date: Mar 2014
Location: Iran
Posts: 642
Thanks: 3,602
Thanked 1,308 Times in 464 Posts
Simorq is on a distinguished road
Hi Razor12911
Could you add support for Traveller's Tales games DAT files?

QuickBMS Script
Code:
# Traveller's Tales games DAT files extractor (script 0.9.11a)
#   Lego Movie: The Video Game
#   LEGO Batman 1
#   LEGO Batman 2
#   LEGO Star Wars
#   LEGO Star Wars III
#   LEGO Indiana Jones
#   LEGO Harry Potter
#   LEGO Pirates of the Caribbean
#   LEGO Lord of the Rings
#   Transformers
#   LEGO Worlds
#   LEGO MARVELs Avengers
#   LEGO Dimensions
#   Lego Marvel Super Heroes
#   Lego Star Wars: The Force Awakens
#   Lego NinjaGO
#   others, check them on http://www.ttgames.com
#
# In case of problems with the extraction try setting NAMELESS to 1
# thanx to who fixed the handling of the names!
#
# Note that the script may not work with the compressed files of
# Lego Movie for PS3, in case of crashes or other issues you can
# extract only the non compressed files by setting
# EXTRACT_COMPRESSED to 0.
#
# script for QuickBMS http://quickbms.aluigi.org

math FORCE_CRC_BITS = 0         # use 32, 64 or 0 for auto-guess, just in case auto-guess fails

quickbmsver "0.8.0"
set NAMELESS long 0             # set to 1 to extract the files without names
set EXTRACT_COMPRESSED long 1   # set to 0 to extract ONLY the non-compressed files
math HAVE_CRCS = 0

math CRC_FNV_OFFSET = 0x811c9dc5
math CRC_FNV_PRIME  = 0x199933

set SIGN_1234567a binary "\x7a\x56\x34\x12"

getdstring SIGN 4
goto 0

if SIGN u== SIGN_1234567a
    goto 0
    callfunction EXTRACT_1234567a 1
    cleanexit
endif

string SIGN f SIGN
math ONE_FILE = 0
  if SIGN == "LZ2K"
    math ONE_FILE = 1
elif SIGN == "DFLT"
    math ONE_FILE = 1
elif SIGN == "ZLIB" # currently doesn't exist
    math ONE_FILE = 1
elif SIGN == "LZMA" # currently doesn't exist
    math ONE_FILE = 1
elif SIGN == "ZIPX"
    math ONE_FILE = 1
elif SIGN == "RFPK"
    math ONE_FILE = 1
elif SIGN == "RNC_"
    math ONE_FILE = 1
elif SIGN == "Defl" # "Deflate_v1.0"
    goto 0
    math OFFSET = 0
    get SIZE asize
    get NAME basename
    get EXT extension
    string NAME + "_unpack."
    string NAME + EXT
    callfunction DEFLATE_UNPACK 1
    cleanexit
endif
if ONE_FILE != 0
    math OFFSET = 0
    get ZSIZE asize
    math SIZE = ZSIZE
    callfunction UNPACK
    log "" 0 SIZE MEMORY_FILE2
    cleanexit
endif

get HDR_NAME basename
string HDR_NAME += ".hdr"
open FDSE HDR_NAME 1 EXISTS

if EXISTS != 0
    get NAME filename
    if NAME == HDR_NAME
        get NAME basename
        string NAME += ".dat"
        open FDSE NAME
    endif
    callfunction HANDLE_COMPRESSED_DAT 1
    get HDR_SIZE asize 1
    log MEMORY_FILE 0 HDR_SIZE 1
    get DUMMY long MEMORY_FILE
else
    callfunction HANDLE_COMPRESSED_DAT 1
    get INFO_OFF long
    if INFO_OFF & 0x80000000
        math INFO_OFF ^= 0xffffffff
        math INFO_OFF <<= 8
        math INFO_OFF += 0x100
    endif
    get INFO_SIZE long
    log MEMORY_FILE INFO_OFF INFO_SIZE
endif

get TYPE_BOH signed_long MEMORY_FILE
get FILES long MEMORY_FILE

math NEW_FORMAT = 1
if TYPE_BOH != 0x3443432e   # game.hdr
if TYPE_BOH != 0x2e434334
if FILES    != 0x3443432e   # game.dat
if FILES    != 0x2e434334
    math NEW_FORMAT = 0
endif
endif
endif
endif

if NEW_FORMAT == 1   # ".CC400TAD"

    goto 0 MEMORY_FILE
    endian big
    get HDR_SIZE long MEMORY_FILE
    idstring MEMORY_FILE ".CC4"
    idstring MEMORY_FILE "0TAD"
    get TYPE_BOH signed_long MEMORY_FILE    # -8
    get NEW_FORMAT_VER long MEMORY_FILE  # 1
    get FILES long MEMORY_FILE
    get NAMES long MEMORY_FILE
    get NAMES_SIZE long MEMORY_FILE
    savepos NAMES_OFF MEMORY_FILE

    math OFFSET = NAMES_OFF
    math OFFSET + NAMES_SIZE
    goto OFFSET MEMORY_FILE

    putarray 10 NAMES ""    # necessary and useful
    putarray 1  NAMES ""    # necessary and useful
    get DUMMY long MEMORY_FILE
    math MYID = 0
    xmath LAST_NAME_WORKAROUND "NAMES - 1"
    for i = 0 < NAMES
        get NAME_OFF long MEMORY_FILE
        get FOLDER_ID short MEMORY_FILE
        if NEW_FORMAT_VER >= 2
            get DUMMY_ID short MEMORY_FILE
        endif
        get SOME_ID signed_short MEMORY_FILE
        get FILE_ID short MEMORY_FILE

        if NAME_OFF != 0xffffffff
            savepos TMP MEMORY_FILE
            math NAME_OFF + NAMES_OFF
            goto NAME_OFF MEMORY_FILE
            get NAME string MEMORY_FILE
            goto TMP MEMORY_FILE

            # I will find a solution another day maybe...
            if i == LAST_NAME_WORKAROUND
                math FILE_ID = MYID
            endif

            getarray PATH 1 FOLDER_ID
            string NAME p "%s\%s" PATH NAME
            if FILE_ID != 0
                putarray 10 MYID NAME
                math MYID + 1
            else
                putarray 1 i NAME
            endif
        endif
    next i

    get TYPE_BOH signed_long MEMORY_FILE    # -8
    get FILES long MEMORY_FILE

    # performance
        putarray 2 FILES 0
        putarray 3 FILES 0
        putarray 4 FILES 0
        putarray 5 FILES 0

    for i = 0 < FILES
        if TYPE_BOH <= -11
            get OFFSET longlong MEMORY_FILE
        else
            get OFFSET long MEMORY_FILE
        endif
        get ZSIZE long MEMORY_FILE
        get SIZE long MEMORY_FILE
        if TYPE_BOH <= -10
            math PACKED = SIZE
            math SIZE & 0x7fffffff
            math PACKED u>> 31
            if PACKED != 0
                math PACKED = 2 # useless, but we need & 2
            endif
        else
            get PACKED byte MEMORY_FILE
            get ZERO short MEMORY_FILE
            get OFFSET2 byte MEMORY_FILE
            math OFFSET u<< 8
            math OFFSET | OFFSET2
        endif
        putarray 2 i OFFSET
        putarray 3 i ZSIZE
        putarray 4 i SIZE
        putarray 5 i PACKED
    next i

    callfunction GET_CRCS 1

    get EXT extension
    if EXT & "DAT"  # both DAT and DAT2
    else
        open FDDE "DAT" # in case HDR has been opened
    endif
    for i = 0 < FILES
        getarray FULLNAME 10 i
        callfunction GET_NAME 1

        getarray OFFSET 2 IDX
        getarray ZSIZE  3 IDX
        getarray SIZE   4 IDX
        getarray PACKED 5 IDX

        callfunction EXTRACT_FILE 1
    next i

else

    savepos INFO_OFF MEMORY_FILE

    math TMP = FILES
    math TMP *= 16
    math NAME_INFO = INFO_OFF
    math NAME_INFO += TMP

    goto NAME_INFO MEMORY_FILE
    get NAMES long MEMORY_FILE
    savepos NAME_INFO MEMORY_FILE

    math NAME_FIELD_SIZE = 8
    if TYPE_BOH <= -5
        math NAME_FIELD_SIZE = 12
    endif

    math TMP = NAMES
    math TMP *= NAME_FIELD_SIZE
    math NAME_OFF = NAME_INFO
    math NAME_OFF += TMP

    goto NAME_OFF MEMORY_FILE
    get NAMECRC_OFF long MEMORY_FILE
    savepos NAME_OFF MEMORY_FILE

    math NAMECRC_OFF += NAME_OFF
    goto NAMECRC_OFF MEMORY_FILE
    callfunction GET_CRCS 1

    if TYPE_BOH <= -2
        get DUMMY1 signed_long MEMORY_FILE
        get DUMMY2 long MEMORY_FILE
    endif

    # print "files:       %FILES%"
    # print "names:       %NAMES%"
    # print "info_off:    %INFO_OFF%"
    # print "info_size:   %INFO_SIZE%"
    # print "name_info:   %NAME_INFO%"
    # print "name_off:    %NAME_OFF%"
    # print "namecrc_off: %NAMECRC_OFF%"

    set NAMEZ long 0
    set FULLNAME string ""
    set FULLPATH string ""

    for i = 0 < FILES
        callfunction SET_NAME 1
        callfunction GET_NAME 1

        math IDX *= 16
        math IDX += INFO_OFF
        goto IDX MEMORY_FILE
        get OFFSET long MEMORY_FILE
        get ZSIZE long MEMORY_FILE
        get SIZE long MEMORY_FILE
        get PACKED threebyte MEMORY_FILE
        get OFFSET2 byte MEMORY_FILE
        if TYPE_BOH == -1
            # do nothing
        else
            math OFFSET <<= 8
        endif
        math OFFSET += OFFSET2

        callfunction EXTRACT_FILE 1
    next i

endif

startfunction GET_CRCS
    math HAVE_CRCS = 0
    putarray 0  FILES 0
    putarray 11 FILES 0
    get TMP1 asize MEMORY_FILE
    savepos TMP2 MEMORY_FILE
    if TMP2 u< TMP1
        xmath TMP4 "TMP2 + (FILES * 4)"
        xmath TMP8 "TMP2 + (FILES * 8)"
        savepos TMP MEMORY_FILE
        goto TMP4 MEMORY_FILE
        get ZERO long MEMORY_FILE
        if ZERO == 0            # this is just a test because there is no good way to guess if it's 64 or 32bit
            math TMP8 = TMP1    # disable 64bit false positives
        endif
        goto TMP MEMORY_FILE
        math CRC_BITS = 32
        if TMP8 u< TMP1 && NEW_FORMAT_VER >= 2  # Lego NinjaGo
            math CRC_BITS = 64
        endif
        if FORCE_CRC_BITS >= 32
            math CRC_BITS = FORCE_CRC_BITS
        endif

        if CRC_BITS == 64
            callfunction QUICKBMS_4GB_CHECK 1
            math CRC_FNV_OFFSET = 0xcbf29ce484222325
            math CRC_FNV_PRIME  = 1099511628211
            math HAVE_CRCS = 2
            for i = 0 < FILES
                get CRC longlong MEMORY_FILE
                putarray 0  i CRC
                putarray 11 i 0 # file has been extracted?
            next i
        elif TMP4 u< TMP1   # no need to check CRC_BITS == 32
            math HAVE_CRCS = 1
            for i = 0 < FILES
                get CRC long MEMORY_FILE
                putarray 0  i CRC
                putarray 11 i 0 # file has been extracted?
            next i
        endif
    endif
    if HAVE_CRCS == 0
            for i = 0 < FILES
                putarray 0  i 0
                putarray 11 i 0 # file has been extracted?
            next i
    endif
endfunction

startfunction EXTRACT_FILE
    endian little   # necessary, they are little endian on big endian archives too
    goto OFFSET
    getdstring SIGN 4
    string SIGN f SIGN
      if SIGN == "LZ2K"
        set PACKED long 2
    elif SIGN == "DFLT"
        set PACKED long 3
    elif SIGN == "ZLIB"
        set PACKED long 3
    elif SIGN == "LZMA"
        set PACKED long 3
    elif SIGN == "ZIPX"
        set PACKED long 3
    elif SIGN == "RFPK"
        set PACKED long 3
    elif SIGN == "RNC_"
        set PACKED long 3
    else
        set PACKED long 0
    endif

    if PACKED & 2   # includes both 2 and 3
        if EXTRACT_COMPRESSED != 0
        callfunction UNPACK
        log FULLNAME 0 SIZE MEMORY_FILE2
        endif
    else
        if SIZE  != 0
        if ZSIZE != 0
        if SIZE  != ZSIZE
            print "SIZE (%SIZE%) and ZSIZE (%ZSIZE%) differ at offset %OFFSET|x%, contact me"
            cleanexit
        endif
        endif
        endif
        log FULLNAME OFFSET SIZE
    endif
endfunction

startfunction SET_NAME
    do
        goto NAME_INFO MEMORY_FILE
        get NEXT signed_short MEMORY_FILE
        get PREV signed_short MEMORY_FILE
        get OFF signed_long MEMORY_FILE
        if TYPE_BOH <= -5   # if NAME_FIELD_SIZE >= 12
            get DUMMY long MEMORY_FILE
        endif
        savepos NAME_INFO MEMORY_FILE

        if OFF < 0
            set NAME string ""
        else
            math OFF += NAME_OFF
            goto OFF MEMORY_FILE
            get NAME string MEMORY_FILE
        endif

        # used only for LEGO the game if you don't use the hdr file
        getvarchr TMP0 NAME 0
        if TMP0 >= 0xf0
            set NAME string ""
        endif
        #string NAME u= NAME # needed for the crc check, but doesn't improve performances so much

        if PREV != 0
            getarray FULLPATH 1 PREV
        endif
        putarray 1 NAMEZ FULLPATH   # putarray 1 NAMEZ NAME
        if NEXT > 0 # folder
            getarray TMP 1 PREV
            if TMP != ""    # long story to avoid things like 2foldername that gives problems to QuickBMS
                set OLDNAME string \    # do not use /
                string OLDNAME += TMP
                string OLDNAME += \     # do not use /
                string FULLPATH >>= OLDNAME
            endif
            if NAME != ""
                #string FULLPATH += \    # do not use /
                string FULLPATH += NAME
                string FULLPATH += \    # do not use /
            endif
        endif
        math NAMEZ += 1
    while NEXT > 0
    set FULLNAME string FULLPATH
    string FULLNAME += NAME
endfunction

startfunction GET_CURRENT_NAME
    for j = 0 < FILES
        getarray TMP 11 j
        if TMP == 0     # the first file not extracted yet
            math IDX = j
            break
        endif
    next j
endfunction

startfunction GET_NAME
    if HAVE_CRCS == 0
        callfunction GET_CURRENT_NAME 1
    else
        getvarchr TMP0 FULLNAME 0
        if TMP0 == '\\'
            string FULLNAME <<= 1
        endif

        math IDX = i
        if NAMELESS == 0
            strlen NAMESZ FULLNAME
            string FULLNAME u= FULLNAME
            string FULLNAME R= / \

            math CRC = CRC_FNV_OFFSET
            for j = 0 < NAMESZ
                getvarchr CHR FULLNAME j
                math CRC ^= CHR
                math CRC *= CRC_FNV_PRIME
            next j
            if HAVE_CRCS <= 1
                math CRC &= 0xffffffff  # quickbms_4gb_files
            endif

            for j = 0 < FILES
                getarray TMP 0 j    # CRC database
                if CRC == TMP
                    math IDX = j
                    break
                endif
            next j
            if j >= FILES
                print "Alert: the crc of the file %FULLNAME% has not been found, I extract the current file"
                callfunction GET_CURRENT_NAME 1
            endif
        else
            set FULLNAME string ""
        endif
    endif
    putarray 11 IDX 1   # the file has been extracted
endfunction

startfunction UNPACK
    putvarchr MEMORY_FILE2 SIZE 0
    log MEMORY_FILE2 0 0
    append
    for TMPSZ = 0 < ZSIZE
        goto OFFSET
        getdstring SIGN 4
        string SIGN f SIGN
          if SIGN == "LZ2K"
            comtype lz2k
            get CHUNK_SIZE long
            get CHUNK_ZSIZE long
        elif SIGN == "DFLT"
            comtype dflt
            get CHUNK_ZSIZE long
            get CHUNK_SIZE long
        elif SIGN == "ZLIB" # currently doesn't exist
            comtype zlib
            get CHUNK_ZSIZE long
            get CHUNK_SIZE long
        elif SIGN == "LZMA" # currently doesn't exist
            comtype lzma
            get CHUNK_ZSIZE long
            get CHUNK_SIZE long
        elif SIGN == "ZIPX"
            comtype deflate # ??? not tested
            get CHUNK_ZSIZE long
            get CHUNK_SIZE long
            string TMP = CHUNK_ZSIZE
            encryption rc4 TMP "" 0 4
        elif SIGN == "RFPK"
            comtype rfpk
            get CHUNK_ZSIZE long
            get CHUNK_SIZE long
        elif SIGN == "RNC_"
            comtype rnc
            math CHUNK_SIZE  = SIZE
            math CHUNK_ZSIZE = ZSIZE
            goto OFFSET
        else
            print "Error: the compressing signature at offset %OFFSET% (%SIGN%) is not known, contact me"
            cleanexit
        endif
        savepos OFFSET
        if CHUNK_ZSIZE == CHUNK_SIZE
            log MEMORY_FILE2 OFFSET CHUNK_SIZE
        else
            clog MEMORY_FILE2 OFFSET CHUNK_ZSIZE CHUNK_SIZE
        endif
        encryption "" ""
        math OFFSET += CHUNK_ZSIZE
        savepos TMP MEMORY_FILE2
        math TMPSZ += 12
        math TMPSZ += CHUNK_ZSIZE
    next
    append
endfunction

startfunction HANDLE_COMPRESSED_DAT
    goto 0
    getdstring TMP 16
    if TMP == "CMP2CMP2CMP2CMP2"
        comtype lzma
        getdstring DAT_HASH 16
        get DAT_SIZE longlong
        savepos DAT_OFFSET
        get DAT_ZSIZE asize
        math DAT_ZSIZE - DAT_OFFSET
        clog TEMPORARY_FILE DAT_OFFSET DAT_ZSIZE DAT_SIZE
        open "." TEMPORARY_FILE
    endif
    goto 0
endfunction

startfunction EXTRACT_1234567a
    idstring "\x7a\x56\x34\x12" # 0x1234567a
    get FILES long
    get PAK_SIZE long
    get CRC long
    get ZERO long
    get ZERO long
    for i = 0 < FILES
        get NAME_OFF long
        get OFFSET long
        get SIZE long
        get DUMMY long  # it's ever 4 in any case
        get ZERO long
        get CRC long
        get ZERO long

        savepos TMP_OFF
        goto NAME_OFF
        get NAME string
        goto OFFSET
        callfunction DEFLATE_UNPACK 1
        goto TMP_OFF
    next i
endfunction

startfunction DEFLATE_UNPACK
    getdstring SIGN 0x20
    if SIGN == "Deflate_v1.0"
        comtype dflt
        get XSIZE long
        math OFFSET + 0x24
        math SIZE   - 0x24
        clog NAME OFFSET SIZE XSIZE
    else
        log NAME OFFSET SIZE
    endif
endfunction

startfunction QUICKBMS_4GB_CHECK
    math TMP64 = 0x10000000
    math TMP64 * 16
    if TMP64 == 0
        print "you must use quickbms_4gb_files.exe with this archive"
        cleanexit
    endif
endfunction
Reply With Quote
Sponsored Links