Skip to content

Commit

Permalink
feat: add new zen2zen example
Browse files Browse the repository at this point in the history
This patch adds a new example which allows conversions between different ZenGin Archive formats and game versions.
  • Loading branch information
lmichaelis committed Feb 15, 2025
1 parent bd6371e commit 3b71ad5
Show file tree
Hide file tree
Showing 2 changed files with 106 additions and 1 deletion.
5 changes: 4 additions & 1 deletion examples/CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,10 @@ target_link_libraries(load_zen PRIVATE zenkit)
add_executable(run_interpreter run_interpreter.cc)
target_link_libraries(run_interpreter PRIVATE zenkit)

set_target_properties(load_vdf load_zen run_interpreter
add_executable(zen2zen zen2zen.cc)
target_link_libraries(zen2zen PRIVATE zenkit)

set_target_properties(load_vdf load_zen run_interpreter zen2zen
PROPERTIES
RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}/bin/examples"
)
102 changes: 102 additions & 0 deletions examples/zen2zen.cc
Original file line number Diff line number Diff line change
@@ -0,0 +1,102 @@
// Copyright © 2025. Luis Michaelis <[email protected]>
// SPDX-License-Identifier: MIT-Modern-Variant
#include "zenkit/vobs/Camera.hh"

#include <zenkit/Archive.hh>
#include <zenkit/SaveGame.hh>
#include <zenkit/World.hh>
#include <zenkit/Logger.hh>

#include <iostream>

void print_usage() {
std::cerr << "Usage: zen2zen [-f FORMAT] [-i VERSION_INPUT] [-o VERSION_OUTPUT] INPUT OUTPUT\n\n"
<< "Converts ZenGin archives from and to different formats.\n\n"
<< "Options:\n"
<< "\t-f FORMAT \t\tSet the output file format (default: ascii)\n"
<< "\t-i,--version-in VERSION_INPUT \t\tSet the game version the archive is from (default: gothic1)\n"
<< "\t-o,--version-out VERSION_OUTPUT\t\tSet the game version the archive should be converted to (default: gothic1)\n\n"
<< "Possible values:\n"
<< "\tFORMAT \t\tascii, binary, binsafe\n"
<< "\tVERSION_INPUT \t\t1, g1, gothic1, 2, g2, gothic2\n"
<< "\tVERSION_OUTPUT\t\t1, g1, gothic1, 2, g2, gothic2\n";
}


int main(int argc, char const** argv) {
if (argc < 3) {
print_usage();
return 1;
}

zenkit::Logger::set_default(zenkit::LogLevel::INFO);
std::vector<char const*> positional;
auto fmt = zenkit::ArchiveFormat::ASCII;
auto ver_input = zenkit::GameVersion::GOTHIC_1;
auto ver_output = zenkit::GameVersion::GOTHIC_1;

for (int i = 1; i < argc; i++) {
if (argv[i][0] != '-') {
if (positional.size() >= 2) {
std::cerr << "Expected only two positionals, ignoring '" << argv[i] << "'\n";
continue;
}
positional.push_back(argv[i]);
continue;
}

std::string_view name = argv[i];
if (name == "-h") {
print_usage();
return 0;
}

if (i + 1 >= argc) {
std::cerr << "Expected value after option '" << name << "'\n";
return 1;
}

std::string_view arg = argv[++i];
if (name == "-f" || name == "--format") {
if (arg == "ascii") fmt = zenkit::ArchiveFormat::ASCII;
else if (arg == "binary") fmt = zenkit::ArchiveFormat::BINARY;
else if (arg == "binsafe") fmt = zenkit::ArchiveFormat::BINSAFE;
else {
std::cerr << "Expected one of 'ascii' (default), 'binary' or 'binsafe' as a format\n";
return 1;
}
} else if (name == "-i" || name == "--version-in") {
if (arg == "1" || arg == "g1" || arg == "gothic1") ver_input = zenkit::GameVersion::GOTHIC_1;
else if (arg == "2" || arg == "g2" || arg == "gothic2") ver_input = zenkit::GameVersion::GOTHIC_2;
else {
std::cerr << "Expected one of '1', 'g1' or 'gothic1' (default) or '2', 'g2' or 'gothic2' as an input version\n";
return 1;
}
} else if (name == "-o" || name == "--version-out") {
if (arg == "1" || arg == "g1" || arg == "gothic1") ver_output = zenkit::GameVersion::GOTHIC_1;
else if (arg == "2" || arg == "g2" || arg == "gothic2") ver_output = zenkit::GameVersion::GOTHIC_2;
else {
std::cerr << "Expected one of '1', 'g1' or 'gothic1' (default) or '2', 'g2' or 'gothic2' as an output version\n";
return 1;
}
} else {
std::cerr << "Unknown option: " << name << "\n";
return 1;
}
}

try {
auto a_in = zenkit::Read::from(positional[0]);
auto a_ar = zenkit::ReadArchive::from(a_in.get());
auto a = a_ar->read_object(ver_input);

auto a_out = zenkit::Write::to(positional[1]);
auto a_ar_o = zenkit::WriteArchive::to(a_out.get(), fmt);
a_ar_o->write_object(a, ver_output);
} catch (const std::exception& e) {
std::cerr << "Error during conversion: " << e.what() << "\n";
return -1;
}

return 0;
}

0 comments on commit 3b71ad5

Please sign in to comment.