I want to extract files from Unravel game, but I didn't find any tools for extract and repack. Can you please help me?
There are two examples of the files: https://mega.nz/#F!XUswVAQJ!F4k19KfxZNMwUsDZk7eQBA
THX

aluigi wrote:The compressed files are splitted in chunks compressed with lz4 but only the first chunks can be decompressed, apparently they maintain the state for the other chunks but even in that way it doesn't work with some files (from file 0x3c0 on).
This script extracts only the compressed files with a size lower than 0x10000:
http://aluigi.org/bms/unravel.bms
Code: Select all
get EXT extension
if EXT != "kit"
print "Error: you must open the small file with the KIT extension"
cleanexit
endif
comtype lz4f
get KIT_NAME filename
idstring "kit!"
get DUMMY long # 1
get DUMMY long # 1
get DUMMY long # 1
get INFO_OFF longlong
get FILES long
get DUMMY long
get DUMMY byte
get DUMMY long
savepos OFFSET
math OFFSET + INFO_OFF
goto OFFSET
math LAST_PAK = -1
for i = 0 < FILES
get FLAGS long
get PAK_NUM short
get OFFSET long
get ZERO short # maybe the 48bit part of OFFSET ?
get ZSIZE longlong
get SIZE longlong
getdstring DUMMY 20
get ZERO long
get DUMMY long
if PAK_NUM != LAST_PAK
string TMP p "%s.%d" KIT_NAME PAK_NUM
open FDSE TMP 1
math LAST_PAK = PAK_NUM
endif
set NAME OFFSET
string NAME p= "0x%08x" NAME
set PAK_NAME PAK_NUM
string PAK_NAME p= "%02x" PAK_NAME
string NAME += "_"
string NAME += PAK_NAME
if ZSIZE == SIZE
log "" OFFSET SIZE 1
else
xmath MEM_SIZE "ZSIZE + 11"
putvarchr MEMORY_FILE MEM_SIZE 0
log MEMORY_FILE 0 0
putVarChr MEMORY_FILE 0 0x184D2204 long
putVarChr MEMORY_FILE 4 0xC04040 threebyte
append
log MEMORY_FILE OFFSET ZSIZE 1
append
get MEM_SIZE asize MEMORY_FILE
putVarChr MEMORY_FILE MEM_SIZE 0 long
get MEM_SIZE asize MEMORY_FILE
putvarchr MEMORY_FILE2 SIZE 0
log MEMORY_FILE2 0 0
clog MEMORY_FILE2 0 MEM_SIZE SIZE MEMORY_FILE
get MEM_SIZE asize MEMORY_FILE2
if MEM_SIZE != 0
log NAME 0 MEM_SIZE MEMORY_FILE2
else
string COMP_NAME = "compressed/"
string COMP_NAME += NAME
log COMP_NAME OFFSET ZSIZE 1
endif
endif
next i
Code: Select all
comtype lz4
get FILE_SIZE asize
putvarchr MEMORY_FILE FILE_SIZE 0
log MEMORY_FILE 0 0
append
do
get ZSIZE long
savepos OFFSET
log MEMORY_FILE OFFSET ZSIZE
math OFFSET += ZSIZE
goto OFFSET
while OFFSET < FILE_SIZE
append
get ZSIZE asize MEMORY_FILE
xmath SIZE "ZSIZE * 10"
get NAME filename
clog NAME 0 ZSIZE SIZE MEMORY_FILE
Code: Select all
get EXT extension
if EXT != "kit"
print "Error: you must open the small file with the KIT extension"
cleanexit
endif
comtype lz4x
get KIT_NAME filename
idstring "kit!"
get DUMMY long
get DUMMY long
get DUMMY long
get INFO_OFF longlong
get FILES long
get DUMMY long
get DUMMY byte
get DUMMY long
savepos OFFSET
math OFFSET + INFO_OFF
goto OFFSET
math LAST_PAK = -1
for i = 0 < FILES
savepos MY_OFF
get FLAGS long
get PAK_NUM short
get OFFSET long
get ZERO short
get ZSIZE longlong
get SIZE longlong
getdstring DUMMY 20
get ZERO long
get DUMMY long
if PAK_NUM != LAST_PAK
string TMP p "%s.%d" KIT_NAME PAK_NUM
open FDSE TMP 1
math LAST_PAK = PAK_NUM
endif
set NAME OFFSET
string NAME p= "0x%08x" NAME
set PAK_NAME PAK_NUM
string PAK_NAME p= "%02x" PAK_NAME
string NAME += "_"
string NAME += PAK_NAME
if ZSIZE == SIZE
log NAME OFFSET SIZE 1
else
clog NAME OFFSET ZSIZE SIZE 1
endif
next i
Code: Select all
int decompress()
{
int i;
#ifdef LZ4_MAGIC
uint magic;
myfread(&magic, 1, sizeof(magic), fin);
if (magic!=LZ4_MAGIC)
return 2;
#endif
int bsize;
while (myfread(&bsize, 1, sizeof(bsize), fin)>0)
{
#ifdef LZ4_MAGIC
if (bsize==LZ4_MAGIC)
continue;
#endif
if (bsize<0 || bsize>COMPRESS_BOUND
|| myfread(&buf[BLOCK_SIZE], 1, bsize, fin)!=bsize)
return 1;
int p=0;
int bp=0;
while (bp<bsize)
{
const int tag=get_byte();
if (tag>=16)
{
int run=tag>>4;
if (run==15)
{
for (;;)
{
const int c=get_byte();
run+=c;
if (c!=255)
break;
}
for ( i=0; i<run; i+=16)
copy128(p+i, BLOCK_SIZE+bp+i);
}
else
copy128(p, BLOCK_SIZE+bp);
p+=run;
bp+=run;
if (bp>=bsize)
break;
}
int s=p-get_byte();
s-=get_byte()<<8;
int len=tag&15;
if (len==15)
{
for (;;)
{
const int c=get_byte();
len+=c;
if (c!=255)
break;
}
}
len+=4;
if ((p-s)>=16)
{
for ( i=0; i<len; i+=16){ // START OF CHANGE
//copy128(p+i, s+i);
for (int j = 0; j < 16; j++) {
int readPos = s + i + j;
if (readPos < 0) {
// need to read from the previously-decoded buffer
int previousBufReadPos = previousBufferLength + readPos;
buf[p + i + j] = previousBuffer[previousBufReadPos];
}
else {
// read from the current buffer
buf[p + i + j] = buf[readPos];
}
}
}
p+=len;
}
else
{
while (len--) {
//buf[p++]=buf[s++];
if (s < 0) {
// need to read from the previously-decoded buffer
int previousBufReadPos = previousBufferLength + s;
buf[p++] = previousBuffer[previousBufReadPos];
s++;
}
else {
buf[p++] = buf[s++];
}
}
} // END OF CHANGE
}
if (bp!=bsize)
return 1;
myfwrite(buf, 1, p, fout);
}
return 0;
}
Code: Select all
513a514
> /*
524a526,528
> */
> while (len--)
> buf[p++] = (s<0) ? fout[s++] : buf[s++];