1. This site uses cookies. By continuing to use this site, you are agreeing to our use of cookies. Learn More.

Black Desert Online Modding Tools

Discussion in 'Tools & Guides' started by BlackFireBR, Jul 7, 2016.

  1. BlackFireBR

    BlackFireBR Club Regular Content Creator

    Joined:
    Sep 2, 2013
    Messages:
    1,135
    Likes Received:
    692
    META INJECTOR
    This tool allows you to put modified files inside the game.​

    What does it do exactly:
    It makes the game look for the files in the Black Desert root folder instead of looking inside the compressed PADxxxxx.PAZ files, so you can use modified files.
    [​IMG]
    Download Link: Meta Injector

    Source Code : src-meta_injector_v1.8.zip
    Old versions:
    list
    Instructions:
    1 - Extract the zip file to your PAZ folder.
    2 - Put all your modified files in the "files_to_patch" folder.
    3 - Run "meta_injector.exe"
    4 - Follow the screen instructions.

    Do this every time a game update is released:
    - Restore you last backup using the tool, before you update the game, otherwise you will get a "corrupted files" message from the launcher and you'll have to re-check the whole game.

    Uninstall:
    Run Meta Injector Reloaded.exe and select the "Restore backup" option.
    The latest ones are the most up to date.

     

    Attached Files:

    Last edited: Mar 14, 2017
    TehPenguin, aliraja, comsci and 5 others like this.
  2. BlackFireBR

    BlackFireBR Club Regular Content Creator

    Joined:
    Sep 2, 2013
    Messages:
    1,135
    Likes Received:
    692
    PAZ Files Browser
    With this tool, you can preview 3D files from the game without having to open or extract the whole game.
    This way you can easily find the corresponding file name for an armor that you want to mod, using my other tools.

    Notice: This tool only allows you to view the file.
    3D Model Exporting and Importing is found further down bellow this page.

    [​IMG]
    The tool uses quickbms to extract the files and 3D Object Coverter to open them.
    Source code here: src-paz_browser_v1.2.zip

    Download: Black Desert Online - Paz Files Browser

    Instructions:
    - Extract ALL files to your "PAZ" folder
    - Run "paz_browser.exe"
    - Use the arrow keys and the ENTER key to navigate through the menu

    [​IMG]

    Important: To visualize the model with textures, click on this icon:
    [​IMG]

    Known issues:
    -If you encounter this message:
    [​IMG]
    - Download this: 3d_object_converter_v6.50.zip and extract all the files to "Black Desert Online\Paz\patcher_resources\3d_converter\"

    Observations:
    - Every file your preview is extracted, both .pac file and texture files under "Black Desert Online\Paz\patcher_resources\extracted_files\".

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Black Desert Online 3D Model Export / Import Tool

    Thanks to IndigoDesert now it's possible to export .pac files open them on any 3D Editor like blender, edit them, and then re-import them back to the game.

    The process is very simple, and I'm going to try to make the explanation as simple as possible with a lot of images to guide you through the process.

    Here we go:
    1. Download Paz Browser and extract ALL THE FILES from the .zip file to: "Black Desert Online\Paz\"
    2. Open your "Paz" folder and run "paz_browser.exe"
    3. Find the .pac file you want to edit and press ENTER to extract and preview the file (Don't close the window that open with the extracted files)
      [​IMG]
      For the nude body models, using the menus, go to "Your class->Body Mesh":

      Here's the list of the nude body models files of each class:
      • Sorceress : phw_00_nude_0001_noalpha.pac
      • Ranger : pew_00_nude_0001_noalpha.pac
      • Tamer : pbw_00_nude_0001.pac
      • Valkyrie : pvw_00_nude_0001.pac
      • Valkyrie : pvw_00_nude_0001.pac
      • Witch : pww_00_nude_0001.pac
      • Kunoichi : pnw_00_nude_0001.pac
      • Dark Knight : pdw_00_nude_0001.pac
      • Plum(Maehwa) : pkww_00_nude_0002.pac
      • Warrior : phm_00_nude_0001.pac
      • Berserker : pgm_00_nude_0001.pac
      • Blader(Musa) : pkm_00_nude_0001.pac
      • Wizard : pwm_00_nude_0001.pac
      • Ninja : pnm_00_nude_0001.pac
    4. Download PAC_to_DAE_Converter_v2.zip and extract all the content to the same folder that contains the .pac file (The folder the program opened after extracting the .pac file)
      4---extract.gif
    5. Right click "pac_to_dae.bat" and then click "Edit"
      5---edit.gif
    6. Replace "PAC_FILE_NAME.pac" with the name of the .pac file you are trying to extract. Also, replace "CLASSPREFIX" with the first 3 letters of the pac file you are converting:
      E.g: If the pac file name is: phw_00_nude_0001_noalpha.pac, replace "CLASSPREFIX_01.pab" with "phw_01.pab"
      [​IMG]
    7. Save the file and run "pac_to_dae.bat". 3 new files will be created in this folder:
      - Each .pac file has 3 "Level of Detail" (LOD) files.
      - When you convert it to .dae, it separates it in 3 different files:
      • lod0 is the one with more details
      • lod3 is the one with less details.
      [​IMG]
    8. Open up Blender or any other 3D Editing software, and go to "File->Import->Collada (default) (.dae)" and find your .dae files.
      [​IMG]
    9. When you are done editing, go to "File->Export->Collada (default) (.dae)" and replace the original file.
      [​IMG]
    10. Now go back to your folder, right click "dae_to_pac.bat" and click on "Edit".
      edit2.gif
    11. Do the same thing you did before, but replace "DAE_FILE_NAME.dae" with the ".dae" file name you just edited and exported, "PAC_FILE_NAME.pac" with the original .pac file name, and "CLASSPREFIX" again with the first 3 letters of the .pac
      edit3.gif
      Note: If you want all the "Level of Detail" to use the same mesh that you just edited, add "-replaceAllLOD" before the "-r"
    12. Run "dae_to_pac.bat"
    13. Now download Meta Injector and extract all the files to: "Black Desert Online\Paz\"
    14. Place the .pac file you just created into "Black Desert Online\Paz\files_to_patch\"
    15. Run "meta_injector.exe"
    16. Choose "Run Injector" and "Let the program decide where they should go."
    If you make new modifications, you have to go through the whole process again, including injecting it with the Meta Injector.
    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    Black Desert Online File Extractor
    View attachment 56142
    A tool that uses quickbms to extract all files from your game

    Download Link:

    Source Code: https://www.undertow.club/attachments/src-file-extractor-v1-1-zip.56139/

    Instructions:
    1 - Extract this zip file to your PAZ folder.
    2 - Run "File Extractor.exe"
    3 - Use the options on the screen to do what you want.

    -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
    How to find the texture from an armor
    - Download: Black Desert Resorepless Mod
    - Extract into your "PAZ" folder.
    - Run "resorepless.exe"
    - Choose option "Tools-> Get Textures from a file"

    Hashes Generator for Meta Injector
    Sometimes the tool won't find the new armor just released for the game, to fix that, you need to generate the file "hashes.txt" again.

    Download the Hashes Generator for Meta Injector, and follow the instructions inside the .zip.
    ---------------------------------------------------------------------------------------------------------------------------------
    Files "Not Found"
    There are around 2% of game files (8000 files) that can't be patched with this tool.
    If you get this message in the end of the program:
    View attachment 55448
    If it's a new armor you are trying to patch, try using the Hashes Generator. Otherwise unfortunately there is nothing it can be done for those files and they will not be recognized by the game.
    ---------------------------------------------------------------------------------------------------------------------------------
    All files must have their original name.
    This means that if you use Resorep texture names like: 472539502.dds won't work.You need to use the original name of the texture like : pbw_00_ub_0001.dds.To do that, use this tool created by Ray Wing:
    ---------------------------------------------------------------------------------------------------------------------------------
    Note1: If you are going to manually move the files, make sure the files are inside their original folders
    For example: pew_00_ub_0034.dds file should be under​
    so when you move or copy, it should go to this path:
    (This doesn't matter if you chose options 1 or 2 of the program though, the program does that for you)
    ----------------------------------------------------------------------------------------------------------------------------------
    meta5.jpg
    PAZ_FILE.jpg
    6---Rename.gif 7---run.gif
     

    Attached Files:

    Last edited: Mar 4, 2017
  3. BlackFireBR

    BlackFireBR Club Regular Content Creator

    Joined:
    Sep 2, 2013
    Messages:
    1,135
    Likes Received:
    692
    Modders Stuff
    This section is reserved to gather all the information I was able to discover so far about the files my tools uses from the game, as well some useful small programs that I made.

    The META File
    The pad00000.meta file, located in your PAZ folder, it's an index file. It tells the game how many .PAZ files there are, which files are in which .PAZ, and their offset, size, etc. When the game needs to load any file, this is where it looks it up to find out where it is.

    The file names and folder names in this files are encrypted using a ICE encryption key (can be found way down below), and the actual files, inside the .PAZ are compressed with a specific algorithm for Black Desert (in quickbms it's the compression algorithm 85) and it's also encrypted with the same ICE key.

    The rest are basically only integer numbers, and you can read their value by reading blocks of 4 bytes at the time, they are not encrypted or anything.

    This is how the pad00000.meta file file is structured:
    Notice: The numbers displayed in this image have changed a lot, but the structure of the file is still the same
    pad00000-layout-new.jpg
    The most important thing you should focus, is the structure I called "File Blocks", this is what tells most of the information about the files. It has these fields:
    HASH| FOLDER_NUM | FILE_NUM | PAZ_NUM | OFFSET | ZSIZE | SIZE |​

    HASH: A Unique number that identifies the file, each file has it's own hash number and you will NEVER find the same number in this file twice. (Unique)

    FOLDER_NUM: Each folder of the game is assigned a number to it, this is used if you have an array of folder names for example, and you use this number to find the right position in the array, corresponding to the folder we are looking for.

    FILE_NUM: Same thing as the folder num. Each file has a number, starting from 0 and ending at the number you read in the PAZ_COUNT variable in the beginning of the meta file.

    PAZ_NUM: The number of the .PAZ this file is located. For example, if this number is 1, the file is located in your file PAD00001.PAZ.

    OFFSET: First byte in the .PAZ which the file is stored

    ZSIZE: The size of the file when it's still compressed, it's how many bytes you have to read in the .PAZ file in order to extract the full compressed file.

    SIZE: The size the file will have, once uncompressed.

    This is how the pad00000.meta file looks like if you open it with a hex edit program:
    [​IMG]


    This is a simplified version of a meta file, with only 3 .PAZ files, 3 folders and 4 files. This is the basic structure of the meta file. The official meta file follows the same pattern, it just has more files in it ( a lot more).

    Before we proceed, this is a few things we need to clarify:
    - Each BIG Block represents 4 bytes.
    - Each small block represents one byte.
    - Red blocks with white background means this is encrypted and they will not appear like this, unless you decrypt those bytes.
    - DUMMY is the client version

    This is the same file as the first image, but with all the numbers converted from hex to dec:
    [​IMG]

    Now let's understand how the game knows which file to load:

    Let's pick the first FILE_HASH: 631490897:

    - We can see it belongs to a file, which folder num is 2
    - When we search for folder num = 2 in the "folders_part" of the file, we find that the name of the folder is "character/" ,so the file is in the "character" folder".
    - next, we know the file number is 0, so the game will look in the "file names part" and when it finds the first '\0', if will know that it's the end of the file name we are looking for. (If file num was == 2, we would have to count 2 '\0', and everything that is between the 2nd and the 3rd '\0' is the file name)

    So we discovered that the file with the hash 631490897 is "multiplemodeldesc.xml" and it's located in "character/"

    One thing you should be aware of, when converting from hex to dec.
    For example, the FILE_HASH we just used: 631490897
    When you convert it to hex, you get this:
    [​IMG]

    But when you look at the meta file, you are not going to find 25 A3 C9 51, instead you need to find 51 C9 A3 25
    [​IMG]


    So everytime you convert to hex, remember to change the order in blocks of 2.

    Warning, don't do this mistake:
    25 A3 C9 51 -> 15 9C 3A 52
    it's:
    25 A3 C9 51 - > 51 C9 A3 25


    PAZ File
    The .PAZ files are all named like this: PAD0xxxx.PAZ and they contain the actual files of the game, also compressed and encrypted, as usual.

    This is how a .PAZ file is structured:
    [​IMG]

    - Light-red colored means encrypted.


    ----------------------------------------------------------------------------------------------------------------------------------------------

    Bonus: ICE Decryption for Black Desert Online in C:
    (Credits to Miau Lightouch)

    Code:
    // ice cipher source: http://www.darkside.com.au/ice/index.html
    #include "ice.h"
    #include <stdio.h>
    #include <stdlib.h>
    #include <stdint.h>
    
    int main (){
    
        FILE *fp, *fout;
    
        int count = 7730712; // copy from folder/file name size
        int count2 = 0;
        fp = fopen("filename.dat","rb"); // encrypted filename block (I dump to a file for test.)
        fout = fopen("output.dat", "wb"); // the file to write out the decrypted text to file.
        uint8_t *ctext = (uint8_t *) malloc(count); // alloc to meet our need.
        uint8_t *ptext = (uint8_t *) malloc(count);
    
    
        if (fp==NULL) {
            perror ("Error opening file");
        }
        else {
            // count2 is the real bytes count that program read out, but should be same as "count".
            count2 = fread(ctext, 1, count, fp);
        printf ("Total number of bytes read: %d\n", count2);
    
        const uint8_t *s = "\x51\xF3\x0F\x11\x04\x24\x6A\x00"; // it's a magic, you know.
    
        ICE_KEY *ik = ice_key_create(0); // init the key
        ice_key_set(ik, s); // set the key
    
        long cuts = count2/8;
        while (cuts--){
            ice_key_decrypt(ik, ctext, ptext); // key, in (encrypted text), out (decrypted text)
            ctext +=8;
            ptext +=8;
        }
    
        ptext -= count2; // reset the pointer back to the begining.
    
        fwrite(ptext, 1, count, fout);
        fclose(fout);
        fclose(fp);
    }
    
    ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

    About the 256000 bytes in red:
    In the NA version of the game, there is the section in the meta file, which is exactly 256000 bytes long, and it contains 8000 file blocks that I simply can't read, because if I read them as integers (4 bytes at the time), it only gives me huge or negative numbers.
    So far I don't know how to read them, but I discovered that all the 8000 missing files that are there, have something in common:
    All of their hashes uses only 7 hexadecimal letters to represent it, instead of 8. Let me explain:
    Let's compare the hashes from "multiplemodeldesc.xml" to the "pew_00_ub_0031_dec_n.dds" (One of the missing files)

    multiplemodeldesc.xml hash:
    DECIMAL: 631490897
    HEX (Big Endian): 25 A3 C9 51
    HEX (Little Endian): 51 C9 A3 25

    pew_00_ub_0031_dec_n.dds hash:
    DECIMAL: 25743895
    HEX (Big Endian): 188D217 (or 01 88 D2 17)
    HEX (Little Endian): 17 D2 88 01

    The complete list of all missing files and their hashes and file/folder numbers can be found here:
    missing_files.txt

    As you can see, when it's one of those files, it when you convert the number from dec to hex, you always get only 7 letters, because the 8th one is always 0

    So what I'm thinking is that, when they made the .meta file, they simply decided not to store this extra "0" to save some space, and since we are always reading 4bytes, it actually reads the seven letters + 1 more of the next field, giving us just nonsense.

    For the KR version, these 256000 bytes are back to normal and they can be read normally

    QUICKBMS Stuff
    I've made a version of the blackdesert.bms file that prints FILE_HASH | FOLDER_NUM | FOLE_NUM | FOLDER_NAME | FILE_NAME reading all from the .meta file:
    quick_bms_script_print.zip

    The only difference is that I manually added the offsets so quickbms would skip those 256,000 bytes.
    Code:
        math OFFSET = 305932  # Pos after the 256,000 bytes (Where the file blocks starts)
        math TMP = 9231156    # Pos after the file blocks ends
        goto TMP
    
    Warning: This number is outdated, you are going to have to find the new value if you want this script to work, by doing this:

    I discovered that number (305932) by doing this:
    - Searching for the hash: 631490897 (from multiplemodeldesc.xml)
    - Go back 28 bytes (7 * 4) (nFields(hash,folderNum,fileNum,pazNum,offset,zsize,size) * sizeof(int))
    - Read hash,folderNum,fileNum,pazNum,offset,zsize,size
    - If pazNum >= 1 or <= 4160
    - Go back 28 bytes
    - repeat.

    Here's the code that does that:
    metaexplorer.c

    So my goal was to find which byte starts the first hash from the "file blocks" section.
    Here is the full list of the file blocks, in the order they appear in the pad000.meta file.
    script-meta-output.txt
    The order is: HASH|FOLDER_NUM|FILE_NUM|PAZ_NUM|FOLDER_NAME|FILE_NAME

    I also made a program that sorts this file by fileNum, and outputs the numbers of the files that are missing and how many of them are missing:
    filesort.zip
    Also, the sorted file is this:
    sorted_file.zip

    Quickbms Fixed Script
    This is a modified version of the original script found at http://aluigi.altervista.org/bms/blackdesert.bms

    In version 0.2.2 you get this error, when you try to extract game's files using pad00000.meta
    Code:
    Error: incomplete input file 0: C:\Program Files (x86)\Black Desert Online\Paz\PAD00000.meta
           Can't read 525213419 bytes from offset 00ffa5c8.
           Anyway don't worry, it's possible that the BMS script has been written
           to exit in this way if it's reached the end of the archive so check it
           or contact its author or verify that all the files have been extracted.
           Please check the following coverage information to know if it's ok.
    
      coverage file 0    45%   7539936    16754120
    
    Last script line before the error or that produced the error:
      50  log MEMORY_FILE2 TMP NAMES_SIZE
    This is a version created by me that works with the updated game and it's all commented

    It tells you what each line does, give you an example in C language of how to do the same thing for a more intuitive understanding, also it prints a lot of useful information while its running like variables values, which file is extracting, what is the hash of that file, the size, how many files were extracted already and the percentage of completeness, etc.

    Code:
    #  This is a modified version of the original script found at
    #  http://aluigi.altervista.org/bms/blackdesert.bms
    #  That makes the script jumps over the 256000 bytes they added in the meta file, after a patch.
    # For a visual guide on how the .meta and .PAZ file is sctructured, see this thread:
    # https://www.undertow.club/posts/129095
    
    quickbmsver "0.7.4"
    comtype blackdesert # Defines the compression type that will be used, when extracting a file
    
    get EXT extension  # gets the extension of the opened file
    
    
    if EXT == "meta" #If the file extension is .meta
    
        # pre-allocation, improves speed (doesn't matter if the values are bigger)
        putarray 0 0x4000  ""   # Array that is going to store the PAZs names
        putarray 1 0x2000  ""   # Array that is going to store the folder names
        putarray 2 0x80000 ""   # Array that is going to store the file names
    
        get DUMMY long        # Reads the first 4 bytes (long) of the meta file and stores it in the variable DUMMY. # In C: fread(&dummy,sizeof(long),1,metaFile);
        get pPAZCount long  # Reads how many PAZ files your game has. # In C: fread(&pPAZCount,sizeof(long),1,metaFile);
        print "pPAZCount: %pPAZCount%"
    
        # Paz files informations
        for i = 0 < pPAZCount
            get PAZ_NUM long
            get HASH long
            get PAZ_SIZE long
    
            string PAZ_NAME p= "PAD%05d.PAZ" PAZ_NUM # Using the number stored in PAZ_NUM with 5 digits,creates a string that will hold the complete .PAZ file name (E.g.:PAD00001.PAZ) # In C: sprintf(paz_name,"PAD%.5d.PAZ",paz_num);
            putarray 0 PAZ_NUM PAZ_NAME                # Stores in the array 0 in the position [PAZ_NUM], the string we just created # In C: array0[paz_num] = paz_name;
        next i
    
        get FILES_COUNT long # Reads how many files your game has. # In C: fread(&files_count,sizeof(long),1,metaFile)
        print "FILES_COUNT: %FILES_COUNT%"
    
        savepos BLOCK_256K_START                             # Saves the current position in the file in a variable. This position is the beginning of a block of 256000 bytes that we need to skip. # In C: long block_256k_start = ftell(metafile);
        print "BLOCK_256K_START: %BLOCK_256K_START%"
    
        xmath BLOCK_256K_END "BLOCK_256K_START + 256000"     # Calculates the byte that the 256000 bytes end # In C: long block_256k_end = block_256k_start + 256000;
        print "BLOCK_256K_END: %BLOCK_256K_END%"
    
        goto BLOCK_256K_END                                    # Skips the 256000 bytes # In C: fseek(metaFile,block_256k_end,SEEK_SET);
    
        savepos FILE_BLOCKS_START        # Saves the current position in the file in a variable. This position is the beginning of the blocks that have the following format: HASH|FOLDER_NUM|FILE_NUM|PAZ_NUM|OFFSET|ZSIZE|SIZE # # In C: long file_blocks_start = ftell(metafile);
        print "FILE_BLOCKS_START: %FILE_BLOCKS_START%"
    
        math FILE_BLOCKS_COUNT = 0        # Counter of how many of those blocks we have # In C: long file_blocks_count = 0;
    
        # Reads the file blocks, just to count how many of them there are, and where do they end, until the PAZ_NUM variable reads something that is out of the interval 1 <= PAZ_NUM <= pPAZCount
        Do
            get HASH long         # The unique indentifier of this file
            get FOLDER_NUM long    # The index in the array 1 (folders array) which has the folder name from this file
            get FILE_NUM long    # The index in the array 2 (files array) which has the file name from this file
            get PAZ_NUM long     # The number of the .PAZ file that the file is located
            get OFFSET long     # The offset inside the .PAZ file specified which the file starts
            get ZSIZE long        # The compressed size of the file
            get SIZE long        # The uncompressed size of the file
    
            if PAZ_NUM <= pPAZCount & PAZ_NUM >= 1
                math FILE_BLOCKS_COUNT += 1         # Counts how many file blocks we have
            endif
    
        While PAZ_NUM <= pPAZCount & PAZ_NUM >= 1 # Condiditon that checks if the PAZ_NUM variable reads something that is out of the interval 1 <= PAZ_NUM <= pPAZCount
    
        savepos CURRENT_POS    # This position should be 28 bytes after the end of the fileblocks, because it read a whole file block before the while checked if it was valid
    
        xmath FILE_BLOCKS_END "CURRENT_POS - (7 * 4)" # Calculates the position which is where the file blocks ended (each file block has 28 bytes (7 * sizeof(long)) # In C: long file_blocks_end = (current pos - 7 * sizeof(long));
        print "FILE_BLOCKS_END: %FILE_BLOCKS_END%"
    
        goto FILE_BLOCKS_END
    
        get FOLDER_NAMES_TOTAL_LENGTH long    # Gets the total length of the strings that are comming next, that are the folder names strings # In C: fread(&folder_names_total_length,sizeof(long),1,metaFile);
        print "FOLDER_NAMES_TOTAL_LENGTH: %FOLDER_NAMES_TOTAL_LENGTH%"
    
        savepos FOLDER_NAMES_START            # Saves the position where the folder names strings start # In C: long folder_names_start = ftell(fp);
        print "FOLDER_NAMES_START: %FOLDER_NAMES_START%"
    
        callfunction SET_ENCRYPTION 1                                    # Decrypts the folder names that are going to be read next
        log MEMORY_FILE FOLDER_NAMES_START FOLDER_NAMES_TOTAL_LENGTH     # Saves all the next "FOLDER_NAMES_TOTAL_LENGTH" bytes, starting from the offset "FOLDER_NAMES_START" in a temporary memory called MEMORY_FILE # In C: fread(memory_file,1,folder_names_total_length,metaFile);
        encryption "" ""                                                # Tells the program to stop decrypting stuff for now
    
        xmath FOLDER_NAMES_END "FOLDER_NAMES_START + FOLDER_NAMES_TOTAL_LENGTH"     # Calculates which byte the folder names strings end # In C: long folder_names_end = folder_names_start + folders_name_total_length;
        print "FOLDER_NAMES_END: %FOLDER_NAMES_END%"
    
        goto FOLDER_NAMES_END                                                         # Goes to that position # In C: fseek(metaFile,folder_names_end,SEEK_SET);
    
        get FILE_NAMES_TOTAL_LENGTH long # Gets the total length of the strings that are comming next, that are the file names strings # In C: fread(&file_names_total_length,sizeof(long),1,metaFile);
        print "FILE_NAMES_TOTAL_LENGTH: %FILE_NAMES_TOTAL_LENGTH%"
    
        savepos FILE_NAMES_START        # Saves the position where the file names strings start # In C: long file_names_start = ftell(fp);
        print "FILE_NAMES_START: %FILE_NAMES_START%"
    
        callfunction SET_ENCRYPTION 1                                # Decrypts the folder names that are going to be read next
        log MEMORY_FILE2 FILE_NAMES_START FILE_NAMES_TOTAL_LENGTH    # Saves all the next "FILE_NAMES_TOTAL_LENGTH" bytes, starting from the offset "FILE_NAMES_START" in a temporary memory called MEMORY_FILE2 # In C: fread(memory_file2,1,file_names_total_length,metaFile);
        encryption "" ""                                            # Tells the program to stop decrypting stuff for now
    
        math FOLDER_NAMES_TOTAL_LENGTH -= 8  # Don't know why, but it ignores the last 8 bytes of the folder names string (2 irrelevent longs, maybe?)
    
        # Reads the string which has all the folder names, assigning each folder name to a different position in the array 1 (folders array)
        print "Collecting folder names..."
        math i = 0
        for TMP = 0 < FOLDER_NAMES_TOTAL_LENGTH
            get INDEX_NUM long MEMORY_FILE      # Reads from the MEMORY_FILE the the index number of the current folder
            get SUB_FOLDERS long MEMORY_FILE    # Reads from the MEMORY_FILE the number of subfolder of the current folder
            get FOLDER_NAME string MEMORY_FILE    # Reads from the MEMORY_FILE a folder name, as string, until a '\0' is found. E.g: "character/"
    
            if FOLDER_NAME == "" # If no name was read, means that we reached the end of the folder names
                break
            endif
    
            putarray 1 i FOLDER_NAME    # Stores the folder name, in the position i of the array 1 (folders array) # In C: array1[i] = folder_name;
    
            savepos TMP MEMORY_FILE
        next i
    
        print "Collecting file names..."
        math i = 0
        # Reads the string which has all the file names, assigning each file name to a different position in the array 2 (files array)
        for TMP = 0 < FILE_NAMES_TOTAL_LENGTH
    
            get FILE_NAME string MEMORY_FILE2         # Reads from the MEMORY_FILE a file name, as string, until a '\0' is found.
    
            if FILE_NAME == ""    # If no name was read, means that we reached the end of the file names
                break
            endif
    
            putarray 2 i FILE_NAME    # Stores the folder name, in the position i of the array 1 (folders array) # In C: array1[i] = file_name;
            savepos TMP MEMORY_FILE2
        next i
    
    
    
        # Now we are going to extract the files, combining the information we find in the file blocks, with the arrays filled with the file and folder names
        goto FILE_BLOCKS_START            # Goes back to the beginning of the file blocks
        for i = 0 < FILE_BLOCKS_COUNT    # For all file blocks
            get HASH long         # The unique indentifier of this file
            get FOLDER_NUM long    # The index in the array 1 (folders array) which has the folder name from this file
            get FILE_NUM long    # The index in the array 2 (files array) which has the file name from this file
            get PAZ_NUM long     # The number of the .PAZ file that the file is located
            get OFFSET long     # The offset inside the .PAZ file specified which the file starts
            get ZSIZE long        # The compressed size of the file
            get SIZE long        # The uncompressed size of the file
    
            getarray PAZ_NAME 0 PAZ_NUM            # Gets the PAZ name at the position [PAZ_NUM] of the array 0 (PAZ names array) and stores is in the PAZ_NAME variable             # In C: paz_name     = array0[paz_num];
            getarray FOLDER_NAME 1 FOLDER_NUM    # Gets the folder name at the position [FOLDER_NUM] of the array 1 (folders array) and stores is in the FOLDER_NAME variable     # In C: folder_name = array1[paz_num];
            getarray FILE_NAME 2 FILE_NUM        # Gets the file name at the position [FILE_NUM] of the array 1 (folders array) and stores is in the FILE_NAME variable             # In C: file_name     = array2[paz_num];
            string FILE_PATH = FOLDER_NAME
            string FILE_PATH += FILE_NAME # Creates a string and concatenates folder name with the file name strings, so we get the full path to the file. Eg: "character/multiplemodeldesc.xml"
    
            open FDSE PAZ_NAME 1    # Open the .PAZ file specified in the PAZ_NAME variable
    
            print "\n[FOLDER NAME]: %FOLDER_NAME%\n[ FILE_NAME ]: %FILE_NAME%\n  HASH   |FOLDER_NUM|FILE_NUM|PAZ_NUM| OFFSET|ZSIZE|SIZE\n%HASH%|   %FOLDER_NUM%   | %FILE_NUM% |  %PAZ_NUM% |%OFFSET%|%ZSIZE%|%SIZE%"
    
            callfunction SET_ENCRYPTION 1
            # If uncompressed size is greater than compressed size, it means that the file is compressed, so we use "clog" which uncompresses and extracts the file
            if SIZE > ZSIZE
    
            # Uncompress and extracts the file and saves it just like is specified in "FILE_PATH", OFFSET is what byte of the .PAZ file the file starts, ZSIZE is the compressed size and SIZE is the uncompressed size, this uses the compression algothithm defined with the "comtype" command
                clog FILE_PATH OFFSET ZSIZE SIZE 1
    
            else  # If uncompressed size is lesser or equal than compressed size, it means that the file is NOT compressed, so we use "log" which just extracts the file
    
            # Simply extracts the file and saves it just like is specified in "FILE_PATH", OFFSET is what byte of the .PAZ file the file start and SIZE is the file size
                log FILE_PATH OFFSET SIZE 1
            endif
            encryption "" ""
    
            print ""
            xmath PERCENTAGE "i*100/FILE_BLOCKS_COUNT"
            print "Files Extracted: %i%/%FILE_BLOCKS_COUNT% (%PERCENTAGE% Percent Completed)"
        next i
    
    
    else if EXT == "PAZ"  #If the file extension is .PAZ
    
        get DUMMY long            # Reads the first 4 bytes (long) of the meta file and stores it in the variable DUMMY. # In C: fread(&dummy,sizeof(long),1,metaFile);
        get TOTAL_FILES long    # Reads how many files this .PAZ file has. # In C: fread(&paz_files,sizeof(long),1,metaFile);
        get FILE_PATHS_TOTAL_LENGTH long     # Gets the total length of the strings that are the folder names and file names like this "character/multiplemodeldesc.xml"
    
        savepos FILE_BLOCKS_START    # Saves the current file's position, which is where the file blocks start # In C: long file_paths_start = ftell(file);
        xmath FILE_BLOCKS_END "FILE_BLOCKS_START + (TOTAL_FILES * 4 * 6)"    # Calculates the position where the file blocks end and it's where the file paths start
        callfunction SET_ENCRYPTION 1                                        # Decrypts the what is going to be read next
        log MEMORY_FILE FILE_BLOCKS_END FILE_PATHS_TOTAL_LENGTH                # Starting for the offset where the file blocks end, it reads the next "FILE_PATHS_TOTAL_LENGTH" bytes and stores them in the MEMORY_FILE file # In C: fread(MEMORY_FILE,1,FILE_PATHS_TOTAL_LENGTH,file);
        encryption "" ""                                                    # Tells the program to stop decrypting stuff for now
    
        # Reads the bytes which has all the file paths, assigning each folder name to a different position in the array 0
        math i = 0
        for TMP = 0 < FILE_PATHS_TOTAL_LENGTH
            get FILE_PATH string MEMORY_FILE # Reads from the MEMORY_FILE a file path, as string, until a '\0' is found. E.g: "character/"
    
            if FILE_PATH == "" # If nothing was read, means that we reached the end of the file paths
                break
            endif
    
            putarray 0 i FILE_PATH # Stores the folder name, in the position i of the array 0  # In C: array0[i] = file_path;
            savepos TMP MEMORY_FILE
        next i
    
        for i = 0 < TOTAL_FILES
            get HASH long         # The unique indentifier of this file
            get FOLDER_NUM long    # The index in the array 0  which has the folder name from this file
            get FILE_NUM long    # The index in the array 0  which has the file name from this file
            get OFFSET long     # The offset inside the .PAZ file specified which the file starts
            get ZSIZE long        # The compressed size of the file
            get SIZE long        # The uncompressed size of the file
    
            getarray FOLDER_NAME 0 FOLDER_NUM    # Gets the folder name at the position [FOLDER_NUM] of the array 1 (folders array) and stores is in the FOLDER_NAME variable     # In C: folder_name = array1[paz_num];
            getarray TMP 0 FILE_NUM        # Gets the file name at the position [FILE_NUM] of the array 1 (folders array) and stores is in the FILE_NAME variable             # In C: file_name     = array2[paz_num];
            string FILE_PATH = FOLDER_NAME
            string FILE_PATH += TMP # Creates a string and concatenates folder name with the file name strings, so we get the full path to the file. Eg: "character/multiplemodeldesc.xml"
    
            print "\n[FOLDER NAME]: %FOLDER_NAME%\n[ FILE_NAME ]: %TMP%\n  HASH   |FOLDER_NUM|FILE_NUM| OFFSET|ZSIZE|SIZE\n%HASH%|   %FOLDER_NUM%   | %FILE_NUM% |%OFFSET%|%ZSIZE%|%SIZE%"
    
            callfunction SET_ENCRYPTION 1
            # If uncompressed size is greater than compressed size, it means that the file is compressed, so we use "clog" which uncompresses and extracts the file
            if SIZE > ZSIZE
    
            # Uncompress and extracts the file and saves it just like is specified in "FILE_FULL_PATH", OFFSET is what byte of the .PAZ file the file starts, ZSIZE is the compressed size and SIZE is the uncompressed size, this uses the compression algothithm defined with the "comtype" command
                clog FILE_PATH OFFSET ZSIZE SIZE
    
            else  # If uncompressed size is lesser or equal than compressed size, it means that the file is NOT compressed, so we use "log" which just extracts the file
    
            # Simply extracts the file and saves it just like is specified in "FILE_FULL_PATH", OFFSET is what byte of the .PAZ file the file start and SIZE is the file size
                log FILE_PATH OFFSET SIZE
            endif
            encryption "" ""
    
        next i
    endif
    
    startfunction SET_ENCRYPTION
            encryption ice "\x51\xF3\x0F\x11\x04\x24\x6A\x00"
    endfunction
    
    

    If you need help understanding quickbms scripts, please refer to http://aluigi.altervista.org/papers/quickbms.txt, everything you need is there.
     
    Last edited: Feb 19, 2017
  4. Hanabikimchi

    Hanabikimchi Potential Patron

    Joined:
    Jan 25, 2013
    Messages:
    8
    Likes Received:
    0
    looks super interesting, I'm looking forward what you can do with that
     
  5. alcaster4242

    alcaster4242 Avid Affiliate

    Joined:
    Mar 12, 2016
    Messages:
    189
    Likes Received:
    44
    Is the png icons working?
    I couldn't get it to work, unless it's a special png file?
     
  6. Kenith

    Kenith Vivacious Visitor

    Joined:
    Mar 7, 2016
    Messages:
    42
    Likes Received:
    66
    Thanx
     
    Last edited: Jul 14, 2016
  7. Kenith

    Kenith Vivacious Visitor

    Joined:
    Mar 7, 2016
    Messages:
    42
    Likes Received:
    66
    I wanna change 'Black garter belt' and find the file of it

    dxt1
    pew_99_ub_0004_02.dds
    pew_99_ub_0004_dec_sp.dds
    dxt5
    pew_99_ub_0004_dec.dds
    pew_99_ub_0004_dec_m.dds
    ( It's used in 'resorep mod')

    but when I run 'meta injector'
    It failed to find 'pew_99_ub_0004_dec.dds' ( maybe main part of 'Bra and Panties' )
     
  8. Jensen

    Jensen Potential Patron

    Joined:
    Jun 4, 2016
    Messages:
    11
    Likes Received:
    0
    hey, this looks really good, but ive been trying to get something but i cant find how, and if its possible
    basically i want Le Vladian underware, i want to remove the underware, just leave the stockings and waist/leg chains

    is this possible ? it used to be before the last patches (EU), then i moved to resorepless and i couldnt do it any more
    any info is appreciated, thanks
     
  9. latuel

    latuel Potential Patron

    Joined:
    Mar 24, 2016
    Messages:
    9
    Likes Received:
    1
    I wanna change Valkyrie's New Clothes texture.
    PVW_00_Ub_076.PAC
    Textures in PAD04089.PAZ(pvw_00_ub_0076.dds, pvw_00_ub_0076_hair.dds)
    How can i do it?
     
  10. BlackFireBR

    BlackFireBR Club Regular Content Creator

    Joined:
    Sep 2, 2013
    Messages:
    1,135
    Likes Received:
    692
    Are you using the original names for those files?
    Does it at least succeed in the "Running Meta Injector" part?
     
  11. BlackFireBR

    BlackFireBR Club Regular Content Creator

    Joined:
    Sep 2, 2013
    Messages:
    1,135
    Likes Received:
    692
    Yeah, I tried to patch that file too, unfortunately it doesn't work.
    I'm trying to see if I can find an alternative for those cases, but I need to study the pad00000.meta file a little more to see if I can do something about it.

    Download this:
    Le Vladian underware textures removed.zip
    - Extract to the "files_to_patch" folder.
    - Run "Meta Injector Reloaded.exe"
    - After done patching, move the folder inside the "files_to_patch" folder to your Black Desert Online root folder.
    Eg:
    If you were in
    "C:\Program Files (x86)\Black Desert Online\PAZ\files_to_patch\"
    you should move the "character" folder to
    "C:\Program Files (x86)\Black Desert Online\"

    Aparently this file doesn't exist in the NA version yet. I just extracted the whole have and I haven't found it.
    You will have to extract it yourself using quickbms and then just follow the instructions from the Meta Injector Reloaded normally.
    Let me know if you need help when extracting the files.
     

    Attached Files:

    Jensen likes this.
  12. Kera

    Kera Vivacious Visitor

    Joined:
    Mar 29, 2016
    Messages:
    28
    Likes Received:
    4
    In the interest of removing a step, would it hurt to just make the final step in your patcher copy the files from files_to_patch into the root folder?

    Maybe make it optional. One of the reasons I do not like moving the files (and would prefer a copy) is that way files_to_patch files just overwrites whatever was in the target directory and keeps it up to date. If you want to tinker, you do it inside of files_to_patch, then just re-run the patcher and it places everything nicely. It also handles deletes - delete from files_to_patch, re-run patcher, and those entries are unpatched so the files can remain where they are without causing issues.
     
  13. Jensen

    Jensen Potential Patron

    Joined:
    Jun 4, 2016
    Messages:
    11
    Likes Received:
    0
    thanks a bunch man, works almost perfectly
    first pic is with transparent resorepless installed, and it works fine
    second pic is the same, but after i press show underware
    2016-07-09_1239850503.jpg
    maybe you know how to fix it ? or maybe i did something wrong
    again, thanks a bunch
     
  14. BlackFireBR

    BlackFireBR Club Regular Content Creator

    Joined:
    Sep 2, 2013
    Messages:
    1,135
    Likes Received:
    692
    Download the Le Vladian underwear textures removed in the post above and follow the instructions I mentioned above.
    This should fix your problem (Assuming you don't want to see the Le Vladian underwear
     
  15. BlackFireBR

    BlackFireBR Club Regular Content Creator

    Joined:
    Sep 2, 2013
    Messages:
    1,135
    Likes Received:
    692
    Black Desert Online Texture Extractor
    [​IMG]
    A tool that uses quickbms to extract only the texture files from your .PAZ files.

    Download Link:

    Source Code: Source Code - Texture Extractor.zip
    Instructions:
    1 - Extract this zip file to your PAZ folder.

    2 - Run "Texture Extractor.exe"

    3 - Press 1 if you want to create a folder called "extracted_textures" in your "PAZ" folder and extract all the textures there.

    4 - Press 2 if you want to specify another folder to extract the textures.

    Note: After the textures are extracted, a file called "log-textures.txt" will be created in your PAZ folder which contains the relation between all .PAZ files number and texture names, this can be useful if you want to extract only a specific file in the future without having to extract all .PAZ files again
     
    alcaster4242 likes this.
  16. alcaster4242

    alcaster4242 Avid Affiliate

    Joined:
    Mar 12, 2016
    Messages:
    189
    Likes Received:
    44
    Nice, been looking for this.
     
  17. BlackFireBR

    BlackFireBR Club Regular Content Creator

    Joined:
    Sep 2, 2013
    Messages:
    1,135
    Likes Received:
    692
    META INJECTOR RELOADED V1.1
    performance-meta-reloaded.jpg
    The program now runs almost twice as fast due to the new copy technique and now in "Part 2" the meta file is loaded in memory instead of accessing the file directly and after all the changes are done, a new file is created and filled with the modified content of the memory.​

    - Added options about what to do with the files in the "files_to_patch" folder after the patch is done:
    NEW-OPTIONS-META-INJECTOR-RELOADED.jpg

    - Added a header to the program showing the version.
    - File count and detection is now made before the first menu shows up
    - The "Running Meta Injector" was renamed to "Part (1/2)"
    - The "Running Meta Patcher" was renamed to "Part (2/2)"
    - Part 1 slightly faster than before.
    - Part 2 insanely faster than before.
    - Now it shows which meta file is chosen in the beginning after the user input in the first menu.
    - Fixed a bug where the same file could result in "not found" or "Success!" in "Part 2" depending on which order of the meta files were used.
     
    Last edited: Jul 9, 2016
    alcaster4242 likes this.
  18. latuel

    latuel Potential Patron

    Joined:
    Mar 24, 2016
    Messages:
    9
    Likes Received:
    1
    [​IMG]

    i'm KR Server.
    Not Found result.

     

    Attached Files:

  19. BlackFireBR

    BlackFireBR Club Regular Content Creator

    Joined:
    Sep 2, 2013
    Messages:
    1,135
    Likes Received:
    692
    Yeah, unfortunately those new files will not be able to be patched. Sorry =/
     
    Last edited: Jul 9, 2016
  20. Chronix

    Chronix Potential Patron

    Joined:
    Apr 24, 2016
    Messages:
    23
    Likes Received:
    1
    Since I started using the metainjector I stopped crashing to desktop in heidel.

    But I found a new problem. It's been a few times now but I get these strange graphical glitches when a valkyrie is wearing Acher Guard armor, atleast the 2 times I saw it it was a valkyrie. I'll try to screenshot it next time.

    Oh yah I don't seem to get the gltich when it is my own valkyrie wearing the armor. (armor swap and pearl shop, dont know if it would be the same if I bought it for real)