# CRI CPK archives (script 0.2.2) # derived from cpk_unpack of hcs # script for QuickBMS http://aluigi.org/papers.htm#quickbms quickbmsver 0.3.12 endian big comtype cpk idstring "CPK " set query->offset long 0 set query->index long 0 set query->name string "TocOffset" callfunction query_utf 1 set toc_offset long UTF_VALUE set query->offset long 0 set query->index long 0 set query->name string "ContentOffset" callfunction query_utf 1 set content_offset long UTF_VALUE set query->offset long 0 set query->index long 0 set query->name string "Files" callfunction query_utf 1 set CpkHeader_count long UTF_VALUE goto toc_offset getdstring signature 4 if signature != "TOC " print "TOC signature not found" cleanexit endif set query->offset long toc_offset set query->index long 0 set query->name string "" callfunction query_utf 1 set CpkHeader_count long UTF_VALUE set toc_entries long table_info.rows # it remains saved after the call if content_offset < 0 # "if" can't be unsigned set add_offset long toc_offset elif toc_offset < 0 set add_offset long content_offset elif content_offset < toc_offset set add_offset long content_offset else set add_offset long toc_offset endif for mytoc = 0 < toc_entries set query->offset long toc_offset set query->index long mytoc set query->name string "DirName" callfunction query_utf 1 set file_name string UTF_VALUE set query->offset long toc_offset set query->index long mytoc set query->name string "FileName" callfunction query_utf 1 set file_name2 string UTF_VALUE string file_name += / string file_name += file_name2 set query->offset long toc_offset set query->index long mytoc set query->name string "FileSize" callfunction query_utf 1 set file_size long UTF_VALUE set query->offset long toc_offset set query->index long mytoc set query->name string "ExtractSize" callfunction query_utf 1 set extract_size long UTF_VALUE set query->offset long toc_offset set query->index long mytoc set query->name string "FileOffset" callfunction query_utf 1 set file_offset long UTF_VALUE math file_offset += add_offset if extract_size > file_size clog file_name file_offset file_size extract_size else log file_name file_offset file_size endif next mytoc startfunction query_utf set COLUMN_STORAGE_MASK long 0xf0 set COLUMN_STORAGE_PERROW long 0x50 set COLUMN_STORAGE_CONSTANT long 0x30 set COLUMN_STORAGE_ZERO long 0x10 set COLUMN_TYPE_MASK long 0x0f set COLUMN_TYPE_DATA long 0x0b set COLUMN_TYPE_STRING long 0x0a set COLUMN_TYPE_FLOAT long 0x08 set COLUMN_TYPE_8BYTE2 long 0x07 set COLUMN_TYPE_8BYTE long 0x06 set COLUMN_TYPE_4BYTE2 long 0x05 set COLUMN_TYPE_4BYTE long 0x04 set COLUMN_TYPE_2BYTE2 long 0x03 set COLUMN_TYPE_2BYTE long 0x02 set COLUMN_TYPE_1BYTE2 long 0x01 set COLUMN_TYPE_1BYTE long 0x00 set UTF_VALUE string "" math offset = query->offset math offset += 0x10 # needed by the tool goto offset set table_info.table_offset long offset getdstring UTF_signature 4 if UTF_signature != "@UTF" print "not a @UTF table at %offset%" cleanexit endif get table_info.table_size long set table_info.schema_offset long 0x20 get table_info.rows_offset long get table_info.string_table_offset long get table_info.data_offset long get table_name_string long get table_info.columns short get table_info.row_width short get table_info.rows long for i = 0 < table_info.columns get schema.type byte get schema.column_name long putarray 0 i schema.type putarray 1 i schema.column_name putarray 2 i -1 # schema.constant_offset math TMP = schema.type math TMP &= COLUMN_STORAGE_MASK if TMP == COLUMN_STORAGE_CONSTANT savepos schema.constant_offset putarray 2 i schema.constant_offset math TMP = schema.type math TMP &= COLUMN_TYPE_MASK if TMP == COLUMN_TYPE_STRING getdstring DUMMY 4 elif TMP == COLUMN_TYPE_DATA getdstring DUMMY 8 elif TMP == COLUMN_TYPE_FLOAT getdstring DUMMY 4 elif TMP == COLUMN_TYPE_8BYTE2 getdstring DUMMY 8 elif TMP == COLUMN_TYPE_8BYTE getdstring DUMMY 8 elif TMP == COLUMN_TYPE_4BYTE2 getdstring DUMMY 4 elif TMP == COLUMN_TYPE_4BYTE getdstring DUMMY 4 elif TMP == COLUMN_TYPE_2BYTE2 getdstring DUMMY 2 elif TMP == COLUMN_TYPE_2BYTE getdstring DUMMY 2 elif TMP == COLUMN_TYPE_1BYTE2 getdstring DUMMY 1 elif TMP == COLUMN_TYPE_1BYTE getdstring DUMMY 1 else print "unknown type for constant" cleanexit endif endif next i math TMP = table_info.string_table_offset math TMP += 8 math TMP += offset math string_table_size = table_info.data_offset math string_table_size -= table_info.string_table_offset log MEMORY_FILE TMP string_table_size for i = query->index < table_info.rows math TMP = i math TMP *= table_info.row_width math row_offset = table_info.table_offset math row_offset += 8 math row_offset += table_info.rows_offset math row_offset += TMP for j = 0 < table_info.columns getarray type 0 j getarray column_name 1 j getarray constant_offset 2 j if constant_offset >= 0 math data_offset = constant_offset else math data_offset = row_offset endif math TMP = type math TMP &= COLUMN_STORAGE_MASK if TMP == COLUMN_STORAGE_ZERO set value long 0 else goto data_offset math TMP = type math TMP &= COLUMN_TYPE_MASK if TMP == COLUMN_TYPE_STRING get string_offset long goto string_offset MEMORY_FILE get value string MEMORY_FILE elif TMP == COLUMN_TYPE_DATA get vardata_offset long get vardata_size long goto vardata_offset MEMORY_FILE getdstring value vardata_size MEMORY_FILE elif TMP == COLUMN_TYPE_FLOAT get value long elif TMP == COLUMN_TYPE_8BYTE2 get DUMMY long # no 64 bit support! get value long elif TMP == COLUMN_TYPE_8BYTE get DUMMY long # no 64 bit support! get value long elif TMP == COLUMN_TYPE_4BYTE2 get value long elif TMP == COLUMN_TYPE_4BYTE get value long elif TMP == COLUMN_TYPE_2BYTE2 get value short elif TMP == COLUMN_TYPE_2BYTE get value short elif TMP == COLUMN_TYPE_1BYTE2 get value byte elif TMP == COLUMN_TYPE_1BYTE get value byte else print "unknown normal type" cleanexit endif if constant_offset < 0 savepos row_offset # row_offset += bytes_read endif endif goto column_name MEMORY_FILE get column_name string MEMORY_FILE if column_name == query->name set UTF_VALUE string value # result.value.value (qthis) math i = table_info.rows # break math j = table_info.columns # break endif next j next i endfunction