![codecov](https://codecov.io/gh/wows-tools/wows-depack/graph/badge.svg?token=GU98T1VKIH)
Open-Source World of Warships resource files unpacker.
Links
Interesting links:
Usage
Build
# Install deps Debian/Ubuntu
apt install git cmake zlib1g-dev libpcre3-dev clang
# git clone + go in project dir
git clone https://github.com/kakwa/wows-depack.git
cd wows-depack/
# build
cmake .
make
CLI tool
Help
./wows-depack-cli --help
Usage: wows-depack-cli [OPTION...] -W WOWS_BASE_DIR
World of Warships resource extractor tool.
[...]
Print all files
To print all the files present:
./wows-depack-cli -W ~/Games/World\ of\ Warships/ -p
/gui/modernization_icons/icon_modernization_PCM020_DamageControl_Mod_I.png
/gui/modernization_icons/icon_modernization_PCM047_Special_Mod_I_Montana.png
[...]
/clanbase/headquarters_2/6/29/31.png
/server_stats.xml
Search
Search files by name pattern (perl compatible regular expression):
./wows-depack-cli -W ~/Games/World\ of\ Warships/ -s '.*[Pp]arams.*'
Found 3 matching files:
shipyardParams.xml
content/GameParams.data
content/UIParams.data
Extract a single file
To Extract a Single file, do:
./wows-depack-cli -W ~/Games/World\ of\ Warships/ \
-e 'content/GameParams.data' -o GameParams.data
Extract a whole directory
To extract a whole sub directory, do:
./wows-depack-cli -W ~/Games/World\ of\ Warships/ \
-e 'content/' -O out/
Extract every World of Warships resource files
To extract everything (rip your free disk space), run:
./wows-depack-cli -W ~/Games/World\ of\ Warships/ \
-e '/' -O out/
Parse Specific index file(s)
Instead of -W/--wows-dir
, a specific index file or directory can be specified through the -i
or -I
options.
Parse a single index file:
./wows-depack-cli -i ~/Games/World\ of\ Warships/bin/6831266/idx/system_data.idx -p
Parse all the indexes in an index directory:
./wows-depack-cli -I ~/Games/World\ of\ Warships/bin/6831266/idx/ -p
Note, the other examples are using -W <WOWS DIR>
, but it could be faster to specify one index file directly through -i <FILE>
. Specifically, GameParams,data
is referenced in the system_data.idx
index.
Also, please note that you will need to adapt the path to your WoWs install and the parent of idx/
(the 6831266
part changes with every update).
Library
API documentation
The API documentation is available here.
Usage examples
Initialize Context & Parse Index Files
To start searching/extracting file, you first need to init & fill the context.
With a single index file:
int ret = wows_parse_index(index_file_path, context);
Definition: wows-depack.h:56
Header file for the wows-depack library.
WOWS_CONTEXT * wows_init_context(uint8_t debug_level)
Initializes a WoWs resource extractor context.
#define WOWS_NO_DEBUG
Definition: wows-depack.h:33
To parse the indexes, you can either specify a specific index file:
char *index_file_path = "Games/World of Warships/bin/6831266/idx/system_data.idx"
int ret = wows_parse_index(index_file_path, context);
Alternatively, you can parse all the index files in a given directory:
char *index_dir_path = "Games/World of Warships/bin/6831266/idx"
int wows_parse_index_dir(const char *index_dir_path, WOWS_CONTEXT *context)
Parses all files in a given directory.
Wows depack also provides a small helper to detect the latest idx directory.
char *index_dir_path;
get_latest_idx_dir("Games/World of Warships/", index_dir_path);
free(index_dir_path);
These operations will parse one or several index files, and construct a pseudo-filesystem tree which can be then explored.
Searching files/directories
It's possible to search for matching files inside the indexes:
int resc;
char **res_files;
char *search_pattern = ".*Params.*";
printf("Found %d matching files:\n", resc);
for (int i = 0; i < resc; i++) {
printf("%s\n", res_files[i]);
free(res_files[i]);
}
free(res_files);
int wows_search(WOWS_CONTEXT *context, char *pattern, int mode, int *result_count, char ***results)
Recursively searches for files in the WOWS archive tree that match a PCRE regular expression pattern.
#define WOWS_SEARCH_FILE_ONLY
Definition: wows-depack.h:41
Extracting Files
To extract files, you can do the following:
char *output = "path/output.xml"
int wows_extract_file(WOWS_CONTEXT *context, char *file_path, char *out_path)
Extract a given file from the archive (output file version).
If you want to control the underlying File Pointer (for example, to write in a memstream), extract functions also provide an _fp
version whenever possible:
char *buf = NULL;
size_t buf_size = 0;
FILE *f = open_memstream(&buf, &buf_size);
fclose(f);
free(buff);
int wows_extract_file_fp(WOWS_CONTEXT *context, char *file_path, FILE *output)
Extract a given file from the archive (file pointer version).
You can also extract files recursively under a given directory:
char *output_dir = "./out/"
int wows_extract_dir(WOWS_CONTEXT *context, char *dir_path, char *out_dir_path)
Extract a given directory (recursively) from the archive (output file version).
Note that with this extract, wows-depack will reproduce the pseudo-filesystem in the archive with output_dir
as its root.
Clean-up
Once done, you need to release the context memory:
int wows_free_context(WOWS_CONTEXT *context)
Frees a WoWs resource extractor context.
Error Handling & Debugging
Most wows_*
returns 0 on success or error codes on failure. To convert it to an error message, you can do the following:
int ret = wows_parse_index(index_file_path, context);
if (ret != 0) {
printf("Error: %s\n", err_msg);
free(err_msg);
}
char * wows_error_string(int error_code, WOWS_CONTEXT *context)
Converts an error code into an error message string for the given WoWs resource parser context.
To print the whole pseudo-filesystem tree to stdout
, you can use the following functions:
int wows_print_flat(WOWS_CONTEXT *context)
Prints the directory tree of the given WoWs resource parser context in a flat format.
int wows_print_tree(WOWS_CONTEXT *context)
Prints the directory tree of the given WoWs resource parser context in a tree format.
Write support
wows-depack provides experimental write support for creating index and pkg files:
char *input_dir = "./tests";
FILE *nfd_pkg = fopen("stuff.pkg", "w+");
FILE *nfd_idx = fopen("stuff.idx", "w+");
fclose(nfd_idx);
fclose(nfd_pkg);
int wows_write_pkg(WOWS_CONTEXT *context, char *in_path, char *name, FILE *pkg_fp, FILE *idx_fp)
Writes a package file and its index.
Please note that the write support is limited, and was created mainly to generate test data.
Build & development
Dependencies
Installing the dependencies on Debian:
apt install cmake zlib1g-dev libpcre3-dev clang
Installing the test/coverage/doc dependencies:
apt install lcov libcunit1-dev doxygen
Build
Install
# Remove DESTDIR for system installation
make install DESTDIR=fakeroot
Files installed:
tree fakeroot
fakeroot
└── usr
└── local
├── bin
│ └── wows-depack-cli
├── include
│ └── wows-depack.h
└── lib
├── libwows-depack.so -> libwows-depack.so.0
├── libwows-depack.so.0 -> libwows-depack.so.0.1.0
└── libwows-depack.so.0.1.0
Tests
To run the unit tests, do the following:
# cmake run (on time)
cmake -DCOVERAGE=ON -DBUILD_TESTS=ON .
# run just the unit tests
make tests
# run also the coverage tests
make coverage
in case of issues, you can directly launch the test binary alone:
# directly:
./wows-depack-test
# or with gdb:
gdb --args ./wows-depack-test
Documentation
To build the doxygen documentation:
cmake -DBUILD_DOC=ON .
make doc_doxygen
Optionally, get a nicer doxygen theme:
./misc/setup_doxycss.sh
make doc_doxygen
Fuzzing
This tool/lib parses binary data, consequently checking for overflow might be a good idea.
To do so, install american fuzzy lop++ (afl++):
# Debian/Ubuntu
apt install afl-clang
# Mac OS
brew install afl-fuzz
Compile with afl support:
cmake -DCMAKE_CXX_COMPILER=afl-clang++ -DCMAKE_C_COMPILER=afl-clang .
make
Run the fuzzing
# Replace with your WoWs install directory
INDEX_DIR="~/Games/World\ of\ Warships/bin/6775398/idx/"
afl-fuzz -i "$INDEX_DIR" -o ./out -t 10000 -- ./wows-depack-cli -i '@@'
Then wait for crashes to occur (hopefully this will be in vain).