Quake Champions

Extraction and unpacking of game archives and compression, encryption, obfuscation, decoding of unknown files
Psychotic Care Bear
Posts: 5
Joined: Mon Oct 15, 2018 2:17 am

Re: Quake Champions

Post by Psychotic Care Bear »

is this still working after the 10/11 update, or am I just doing it wrong

quickbms -> qc.bms -> pak -> folder, that is right?

just trying to get at the pct's in initial.pak
h3x3r
Posts: 165
Joined: Wed Jun 01, 2016 5:53 pm

Re: Quake Champions

Post by h3x3r »

Doesn't work since last HUGE update. Seems like seed key was changed too... Output looked weird.
aluigi
Site Admin
Posts: 12984
Joined: Wed Jul 30, 2014 9:32 pm

Re: Quake Champions

Post by aluigi »

Just new seed or new format too?
h3x3r
Posts: 165
Joined: Wed Jun 01, 2016 5:53 pm

Re: Quake Champions

Post by h3x3r »

This is what script throw...

Code: Select all



  offset           filesize   filename
--------------------------------------

- the script needs to load a pre-compiled function from the dll or code
  MEMORY_FILE10
  do you want to continue with this and any other requested dll/code (y/N)?
  y
- library MEMORY_FILE10 loaded at address 00BC2F40
- function found at offset 00BC10AD
- function found at offset 00BC113A
  000000000000001e 140        [dOtabase]ß_\abiliéy_cooldwn.tpl

- it's not possible to create that file due to its filename or related
  incompatibilities (for example already exists a folder with that name), so
  now you must choose a new filename for saving it.
  if you press ENTER a new name will be generated automatically.
  - old: [dOtabase]ß_\abiliéy_cooldwn.tpl
  - new: a

- signature of 4 bytes at offset 0x0000000000000000 doesn't match the one
  expected by the script:

  this one: "]Lõ"
  5d 18 4c f5                                       ].L.

  expected: "PK"
  50 4b 01 02                                       PK..

- 1 files found in 231 seconds
  coverage file 0     0%   8463       13477777408 . offset 00000003234418eb
  coverage file -1    8%   4          46         . offset 0000000000000004
  coverage file -10   0%   0          1508       . offset 0000000000000000

Press ENTER or close the window to quit
z65536
Posts: 11
Joined: Thu Aug 30, 2018 3:13 pm

Re: Quake Champions

Post by z65536 »

The constant was changed. The new one is 0x0F10C856F
Rhoken
Posts: 7
Joined: Wed Oct 17, 2018 2:41 pm

Re: Quake Champions

Post by Rhoken »

Seems doesn't work also with the new constant: 0x0F10C856F

Give me this error and no files are extracted. tried with the "quakechampions.bms" script and quickBMS 4gb file...

Image
z65536
Posts: 11
Joined: Thu Aug 30, 2018 3:13 pm

Re: Quake Champions

Post by z65536 »

Rhoken wrote:Seems doesn't work also with the new constant: 0x0F10C856F

Give me this error and no files are extracted. tried with the "quakechampions.bms" script and quickBMS 4gb file...

Image

Try this script

Code: Select all

# Quake Champions
# script for QuickBMS http://quickbms.aluigi.org

quickbmsver "0.8.0"
set MEMORY_FILE10 string "
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned long long ulong;

    // Numerical Recipes 3rd edition
    static ulong u, v, w;

    ulong NextUInt64()
    {
      u = u * 2862933555777941757ULL + 7046029254386353087ULL;
      v ^= v >> 17; v ^= v << 31; v ^= v >> 8;
      w = 4294957665U * (w & 0xffffffff) + (w >> 32);
      ulong x = u ^ (u << 21); x ^= x >> 35; x ^= x << 4;
      return (x + v) ^ w;
    }

    void NrRandom(ulong seed)
    {
      v = 4101842887655102017ULL;
      w = 1;

      u = v ^ seed ^ 0x0F10C856F; NextUInt64();
      v = u;                     NextUInt64();
      w = v;                     NextUInt64();
    }

// Quake Champions
static ulong    qc_seed = 0;
static uchar    qc_ivec[32] = {0};
static ushort   qc_seed_idx = 0;
static ushort   qc_ivec_idx = 0;

void quake_decrypt_init(uchar *key) {
   int     i;
   for(i = 0; i < sizeof(qc_ivec); i++) {
      qc_ivec[i] = key[i];
   }
   qc_seed = *(ulong *)key;
   qc_seed_idx = 0;
   qc_ivec_idx = 0;
   NrRandom(qc_seed);
}

int quake_decrypt(unsigned char *data, int size) {
    int     i;
    for(i = 0; i < size; i++) {
        uchar old = qc_ivec[qc_ivec_idx];
        qc_ivec[qc_ivec_idx] = data[i] ;
        data[i] ^= (qc_seed_idx == 0 ? qc_seed :0) ^ old ;
        qc_ivec_idx = (qc_ivec_idx + 1) & 0x1f;
        if(++qc_seed_idx == 8) {
            qc_seed = NextUInt64();
            qc_seed_idx = 0;
        }
    }
    return size;
}
"

goto -40
getdstring KEY 40
calldll MEMORY_FILE10 "quake_decrypt_init" "tcc" RET KEY
findloc OFFSET binary "PK\x06\x06" 0 "" 0
goto OFFSET
idstring "PK\x06\x06"
   get ZERO byte
   get central_entries longlong
   get central_size longlong
   get central_offset longlong
   get DUMMY_offset longlong

goto central_offset
for i = 0 < central_entries

    savepos TMP
    log MEMORY_FILE TMP 0x2e
    calldll MEMORY_FILE10 "quake_decrypt" "tcc" RET MEMORY_FILE 0x2e
    goto 0x2e 0 SEEK_CUR

    goto 0 MEMORY_FILE
    idstring MEMORY_FILE "PK\x01\x02"
        get ver_made        short MEMORY_FILE
        get ver_need        short MEMORY_FILE
        get flag            short MEMORY_FILE
        get method          short MEMORY_FILE
        get modtime         short MEMORY_FILE
        get moddate         short MEMORY_FILE
        get zip_crc         long MEMORY_FILE
        get comp_size       long MEMORY_FILE
        get uncomp_size     long MEMORY_FILE
        get name_len        short MEMORY_FILE
        get extra_len       short MEMORY_FILE
        get comm_len        short MEMORY_FILE
        get disknum         short MEMORY_FILE
        get int_attr        short MEMORY_FILE
        get ext_attr        long MEMORY_FILE
        get rel_offset      long MEMORY_FILE

    savepos TMP
    log MEMORY_FILE TMP name_len
    calldll MEMORY_FILE10 "quake_decrypt" "tcc" RET MEMORY_FILE name_len
    goto name_len 0 SEEK_CUR

    goto 0 MEMORY_FILE
        getdstring name     name_len MEMORY_FILE

        # not encrypted
        getdstring extra    extra_len
        getdstring comment  comm_len

      if extra_len >= 12
         getvarchr extra_id extra 0 short
         if extra_id == 0x0001
            if rel_offset == 0xffffffff
               getvarchr rel_offset extra 4 longlong
            endif
         endif
      endif
     
    math offset = 0x1e
    math offset + rel_offset

        if method == 0
            Log name offset uncomp_size # same as comp_size
            #Log name offset comp_size   # was uncomp_size before AES
        else
            if method == 8
                ComType deflate
            else
                print "unsupported compression method %method%"
                cleanexit
            endif
            CLog name offset comp_size uncomp_size
        endif
next i
Rhoken
Posts: 7
Joined: Wed Oct 17, 2018 2:41 pm

Re: Quake Champions

Post by Rhoken »

z65536 wrote:
Rhoken wrote:Seems doesn't work also with the new constant: 0x0F10C856F

Give me this error and no files are extracted. tried with the "quakechampions.bms" script and quickBMS 4gb file...

Image

Try this script

Code: Select all

# Quake Champions
# script for QuickBMS http://quickbms.aluigi.org

quickbmsver "0.8.0"
set MEMORY_FILE10 string "
typedef unsigned char uchar;
typedef unsigned short ushort;
typedef unsigned long long ulong;

    // Numerical Recipes 3rd edition
    static ulong u, v, w;

    ulong NextUInt64()
    {
      u = u * 2862933555777941757ULL + 7046029254386353087ULL;
      v ^= v >> 17; v ^= v << 31; v ^= v >> 8;
      w = 4294957665U * (w & 0xffffffff) + (w >> 32);
      ulong x = u ^ (u << 21); x ^= x >> 35; x ^= x << 4;
      return (x + v) ^ w;
    }

    void NrRandom(ulong seed)
    {
      v = 4101842887655102017ULL;
      w = 1;

      u = v ^ seed ^ 0x0F10C856F; NextUInt64();
      v = u;                     NextUInt64();
      w = v;                     NextUInt64();
    }

// Quake Champions
static ulong    qc_seed = 0;
static uchar    qc_ivec[32] = {0};
static ushort   qc_seed_idx = 0;
static ushort   qc_ivec_idx = 0;

void quake_decrypt_init(uchar *key) {
   int     i;
   for(i = 0; i < sizeof(qc_ivec); i++) {
      qc_ivec[i] = key[i];
   }
   qc_seed = *(ulong *)key;
   qc_seed_idx = 0;
   qc_ivec_idx = 0;
   NrRandom(qc_seed);
}

int quake_decrypt(unsigned char *data, int size) {
    int     i;
    for(i = 0; i < size; i++) {
        uchar old = qc_ivec[qc_ivec_idx];
        qc_ivec[qc_ivec_idx] = data[i] ;
        data[i] ^= (qc_seed_idx == 0 ? qc_seed :0) ^ old ;
        qc_ivec_idx = (qc_ivec_idx + 1) & 0x1f;
        if(++qc_seed_idx == 8) {
            qc_seed = NextUInt64();
            qc_seed_idx = 0;
        }
    }
    return size;
}
"

goto -40
getdstring KEY 40
calldll MEMORY_FILE10 "quake_decrypt_init" "tcc" RET KEY
findloc OFFSET binary "PK\x06\x06" 0 "" 0
goto OFFSET
idstring "PK\x06\x06"
   get ZERO byte
   get central_entries longlong
   get central_size longlong
   get central_offset longlong
   get DUMMY_offset longlong

goto central_offset
for i = 0 < central_entries

    savepos TMP
    log MEMORY_FILE TMP 0x2e
    calldll MEMORY_FILE10 "quake_decrypt" "tcc" RET MEMORY_FILE 0x2e
    goto 0x2e 0 SEEK_CUR

    goto 0 MEMORY_FILE
    idstring MEMORY_FILE "PK\x01\x02"
        get ver_made        short MEMORY_FILE
        get ver_need        short MEMORY_FILE
        get flag            short MEMORY_FILE
        get method          short MEMORY_FILE
        get modtime         short MEMORY_FILE
        get moddate         short MEMORY_FILE
        get zip_crc         long MEMORY_FILE
        get comp_size       long MEMORY_FILE
        get uncomp_size     long MEMORY_FILE
        get name_len        short MEMORY_FILE
        get extra_len       short MEMORY_FILE
        get comm_len        short MEMORY_FILE
        get disknum         short MEMORY_FILE
        get int_attr        short MEMORY_FILE
        get ext_attr        long MEMORY_FILE
        get rel_offset      long MEMORY_FILE

    savepos TMP
    log MEMORY_FILE TMP name_len
    calldll MEMORY_FILE10 "quake_decrypt" "tcc" RET MEMORY_FILE name_len
    goto name_len 0 SEEK_CUR

    goto 0 MEMORY_FILE
        getdstring name     name_len MEMORY_FILE

        # not encrypted
        getdstring extra    extra_len
        getdstring comment  comm_len

      if extra_len >= 12
         getvarchr extra_id extra 0 short
         if extra_id == 0x0001
            if rel_offset == 0xffffffff
               getvarchr rel_offset extra 4 longlong
            endif
         endif
      endif
     
    math offset = 0x1e
    math offset + rel_offset

        if method == 0
            Log name offset uncomp_size # same as comp_size
            #Log name offset comp_size   # was uncomp_size before AES
        else
            if method == 8
                ComType deflate
            else
                print "unsupported compression method %method%"
                cleanexit
            endif
            CLog name offset comp_size uncomp_size
        endif
next i


Seems to work now, thanks. Now on the go to find how to open the various "proprietary" extension files
Rhoken
Posts: 7
Joined: Wed Oct 17, 2018 2:41 pm

Re: Quake Champions

Post by Rhoken »

Alright, after i extracted the files... now seems impossible to use this files.

.PCT files are the texture files but ANY version of QCPCT give me a corrupted images
.hkx files remember me some animation files from Skyrim
.TPL files maybe is the model but i don't find any tool to extract it.

So now is a good goal that we have a working method to extract files from pak (before they release a new update), but the problem begin now on how to extract these files..
z65536
Posts: 11
Joined: Thu Aug 30, 2018 3:13 pm

Re: Quake Champions

Post by z65536 »

I’m creating python script that can convert .pct files.

.pct header structure

Code: Select all

6 byte : Unknown
4 byte : String 'TCIP'
6 byte : Unknown
4 byte : Width
4 byte : Height
4 byte : Number of frames?
4 byte : Number of images?
6 byte : Unknown
1 byte : Texture format
9 byte : Unknown
4 byte : Number of addresses
6 byte : Unknown

4 byte : Data address offset
4 byte : Data size

2 byte : Unknown
4 byte : Size of data section

Data section

2 byte : Unknown
4 byte : File size

List of texture format

Code: Select all

0x34 = DXGI_FORMAT_BC7_UNORM
0x33 = DXGI_FORMAT_BC7_UNORM_SRGB
0x31 = DXGI_FORMAT_BC6H_UF16
0x26 = DXGI_FORMAT_R16G16B16A16_SNORM
0x25 = DXGI_FORMAT_BC4_UNORM
0x24 = DXGI_FORMAT_BC5_UNORM
0x16 = DXGI_FORMAT_B8G8R8X8_UNORM_SRGB?
0x11 = DXGI_FORMAT_BC3_UNORM_SRGB?
0xc = DXGI_FORMAT_BC1_UNORM
0x3 = DXGI_FORMAT_R8_UNORM?
0x0 = DXGI_FORMAT_B8G8R8A8_UNORM_SRGB?
Last edited by z65536 on Thu Oct 18, 2018 9:06 am, edited 2 times in total.
h3x3r
Posts: 165
Joined: Wed Jun 01, 2016 5:53 pm

Re: Quake Champions

Post by h3x3r »

Here are compressions which i got from PCT.

Code: Select all

HEX = 03 = ??
HEX = 11 = CUBEMAP
HEX = 0C = BC1 UNORM/sRGB
HEX = 16 = ?? RGBA8 UNORM/sRGB ??
HEX = 24 = ATI2
HEX = 25 = ATI1
HEX = 31 = ?? HDR ??
HEX = 33 = BC7 UNORM/sRGB
HEX = 34 = BC7 UNORM/sRGB

And thanks for seed key.
z65536
Posts: 11
Joined: Thu Aug 30, 2018 3:13 pm

Re: Quake Champions

Post by z65536 »

PCT converter alpha is here.

Usage
Download Rawtex. https://zenhax.com/viewtopic.php?t=7099
Put pctcnv.exe in the same folder as RawtexCmd.exe.
Run command:
pctcnv.exe <Path to folder>
Rhoken
Posts: 7
Joined: Wed Oct 17, 2018 2:41 pm

Re: Quake Champions

Post by Rhoken »

z65536 wrote:PCT converter alpha is here.

Usage
Download Rawtex. https://zenhax.com/viewtopic.php?t=7099
Put pctcnv.exe in the same folder as RawtexCmd.exe.
Run command:
pctcnv.exe <Path to folder>



CMD say me: "error: invalid argument" when i try to run pctcnv.exe in this way:

"cd /d d:
D:\>cd D:\Desktop\quickbms\Nuova cartella\[textures]\characters
D:\Desktop\quickbms\Nuova cartella\[textures]\characters> pctcnv.exe
error: invalid argument"

I have put pctcnv.exe in the same folder with RawTexCmd.exe but if i run also this exe doesn't show anything (so i presume i need to run in CMD)
If i write after pctcnv.exe the path folder with the name of the .pct file says me "syntax error"

I am missing something?
Psychotic Care Bear
Posts: 5
Joined: Mon Oct 15, 2018 2:17 am

Re: Quake Champions

Post by Psychotic Care Bear »

if you ran it without the pathtofolder argument I could see why you get the invalid argument error

when I made a .bat file to run it, it also didn't seem to like spaces in the path to folder

I dunno if you tried specifying a specific pct file, but it only does whole folders

imo, just copy the folder you want to convert to the folder with pctcnv.exe and rawtexcmd.exe, make a .bat file with the following text:
pctcnv.exe nameofyourfoldertoconvert
h3x3r
Posts: 165
Joined: Wed Jun 01, 2016 5:53 pm

Re: Quake Champions

Post by h3x3r »

Just create txt and put to it:
pctcnv.exe [textures] and save as bat file.

Now copy that bat file and also pctcnv.exe, Rawtex.exe, RawtexCmd.exe and texconv.exe to the same folder where you have unpacked your game files and run bat file.
I did it this way and it works flawless.
Rhoken
Posts: 7
Joined: Wed Oct 17, 2018 2:41 pm

Re: Quake Champions

Post by Rhoken »

h3x3r wrote:Just create txt and put to it:
pctcnv.exe [textures] and save as bat file.

Now copy that bat file and also pctcnv.exe, Rawtex.exe, RawtexCmd.exe and texconv.exe to the same folder where you have unpacked your game files and run bat file.
I did it this way and it works flawless.



Maybe i am an fool and i do all wrong again, but i create a .bat file with the string you say me, i put in the folder with the other executable, but if i open this bat i see for some seconds a cmd window and he close automatically. Of course i insert the bat file in the "textures" folder with other programs..

Is write like this the right bat file?

Image
Psychotic Care Bear
Posts: 5
Joined: Mon Oct 15, 2018 2:17 am

Re: Quake Champions

Post by Psychotic Care Bear »

Image

this pic shows what I did and locations, in my example the folder I want to convert is QCChampFiles(2018-10-11), so I have to run:
pctcnv.exe QCChampFiles(2018-10-11)

this will output the *.dds for each *.pct file in that directory, for you to open in whatever program you want, I used visual studio since every other program I tried gave me rainbow noise, lol
Rhoken
Posts: 7
Joined: Wed Oct 17, 2018 2:41 pm

Re: Quake Champions

Post by Rhoken »

Psychotic Care Bear wrote:Image

this pic shows what I did and locations, in my example the folder I want to convert is QCChampFiles(2018-10-11), so I have to run:
pctcnv.exe QCChampFiles(2018-10-11)

this will output the *.dds for each *.pct file in that directory, for you to open in whatever program you want, I used visual studio since every other program I tried gave me rainbow noise, lol



Now seems to work, thanks

but dds texture seems to be corrupted: in photoshop with dds plugin is all black, with DXTBmp doesn't load anything, DDSViewer crash when i try to load one... or seems they have a obnoxious proprietary "color palette" (like the models)...
Psychotic Care Bear
Posts: 5
Joined: Mon Oct 15, 2018 2:17 am

Re: Quake Champions

Post by Psychotic Care Bear »

Rhoken wrote:
but dds texture seems to be corrupted: in photoshop with dds plugin is all black, with DXTBmp doesn't load anything, DDSViewer crash when i try to load one... or seems they have a obnoxious proprietary "color palette" (like the models)...


I had the same issue, that's why I used Visual Studio, which I already had installed, its probably your viewer doesn't support later versions of dds or something stupid like that

OR

you could use Paint.net download link along with this filetype plugin, follow the instructions in the plugin zip readme to install

NOTE: to load them you must rename the dds files to dds2 files for the time being

OR

for Photoshop use this
z65536
Posts: 11
Joined: Thu Aug 30, 2018 3:13 pm

Re: Quake Champions

Post by z65536 »

Script updated

Changed to convert the file of the current and sub folder by double click.
Fixed to be able to convert specific files.
Fixed detection of necessary files.