diff --git a/CMakeLists.txt b/CMakeLists.txt index 0930688..d0a871c 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -49,4 +49,4 @@ endif() include_directories(${CMAKE_CURRENT_BINARY_DIR}) -add_subdirectory(src) \ No newline at end of file +add_subdirectory(src) diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt index 6d133ac..d80ab93 100644 --- a/src/CMakeLists.txt +++ b/src/CMakeLists.txt @@ -11,6 +11,7 @@ endif() file(GLOB script2txt_src "script2txt/*") add_executable(script2txt ${script2txt_src}) +target_link_libraries(script2txt common) if (DATA_MANAGER_DIR) diff --git a/src/common/common.h b/src/common/common.h new file mode 100644 index 0000000..e0c9406 --- /dev/null +++ b/src/common/common.h @@ -0,0 +1,40 @@ +/* +* AIM tools +* Copyright (C) 2015 lzwdgc +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#pragma once + +#include + +template +bool replace_all(T &str, const T &from, const T &to) +{ + bool replaced = false; + size_t start_pos = 0; + while ((start_pos = str.find(from, start_pos)) != T::npos) + { + str.replace(start_pos, from.length(), to); + start_pos += to.length(); + replaced = true; + } + return replaced; +} + +inline bool replace_all(std::string &str, const std::string &from, const std::string &to) +{ + return replace_all(str, from, to); +} diff --git a/src/script2txt/script.h b/src/script2txt/script.h new file mode 100644 index 0000000..e8a9c3c --- /dev/null +++ b/src/script2txt/script.h @@ -0,0 +1,135 @@ +/* +* AIM script2txt +* Copyright (C) 2015 lzwdgc +* +* This program is free software: you can redistribute it and/or modify +* it under the terms of the GNU General Public License as published by +* the Free Software Foundation, either version 3 of the License, or +* (at your option) any later version. +* +* This program is distributed in the hope that it will be useful, +* but WITHOUT ANY WARRANTY; without even the implied warranty of +* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +* GNU General Public License for more details. +* +* You should have received a copy of the GNU General Public License +* along with this program. If not, see . +*/ + +#pragma once + +#include + +#include +#include + +struct script +{ + uint32_t file_size; + uint32_t unk0; + uint32_t raw_text_size; + uint32_t unk1; + std::vector raw_text; + uint32_t array_len; + std::vector unk2; + + // + std::vector lines; + + void load(buffer &b) + { + READ(b, file_size); + READ(b, unk0); + READ(b, raw_text_size); + READ(b, unk1); + raw_text.resize(raw_text_size); + READ_N(b, raw_text[0], raw_text.size()); + READ(b, array_len); + unk2.resize(array_len); + READ_N(b, unk2[0], unk2.size()); + + if (!b.eof()) + { + std::stringstream ss; + ss << std::hex << b.index() << " != " << std::hex << b.size(); + throw std::logic_error(ss.str()); + } + + fix_text(); + beautify(); + } + + void fix_text() + { + std::string line; + for (size_t i = 0; i < raw_text.size(); i++) + { + if (raw_text[i] == 0) + { + lines.push_back(line); + line.clear(); + } + else + line.push_back(raw_text[i]); + } + } + + void beautify() + { + const std::string space = " "; + int brace_count = 0; + int proc_started = 0; + for (auto &line : lines) + { + if (brace_count > 0 || proc_started > 0) + { + auto space_count = brace_count + proc_started; + if (line == "}" || + (brace_count == 0 && proc_started == 1 && + line.find("END") != line.npos)) + space_count--; + std::string s; + for (int i = 0; i < space_count; i++) + s += space; + line = s + line; + } + if (line.find("PROC") != line.npos && + line.find("()") != line.npos) + { + proc_started++; + continue; + } + if (line.find("END") != line.npos && proc_started == 1) + { + proc_started--; + } + for (auto &c : line) + { + if (c == '{') + brace_count++; + else if (c == '}') + brace_count--; + if (brace_count < 0) + { + c = '\n'; + brace_count++; + } + } + } + } + + std::string get_text() const + { + std::string s; + for (auto &line : lines) + { + if (line != "\n") + s += line + "\n"; + } + replace_all(s, "IF(", "IF ("); + replace_all(s, "\nIF", "\n\nIF"); + replace_all(s, "PROC", "PROC "); + replace_all(s, "END\nPROC", "END\n\nPROC"); + return s; + } +}; diff --git a/src/script2txt/script2txt.bat b/src/script2txt/script2txt.bat new file mode 100644 index 0000000..60c0b7d --- /dev/null +++ b/src/script2txt/script2txt.bat @@ -0,0 +1,2 @@ +@for /r %%v in (*.scr) do script2txt.exe "%%v" +@for /r %%v in (*.QST) do script2txt.exe "%%v" diff --git a/src/script2txt/script2txt.cpp b/src/script2txt/script2txt.cpp index c2cdc74..3b025e3 100644 --- a/src/script2txt/script2txt.cpp +++ b/src/script2txt/script2txt.cpp @@ -16,47 +16,46 @@ * along with this program. If not, see . */ +#include #include #include -using namespace std; +#include "script.h" + +using std::cout; +using std::string; int main(int argc, char *argv[]) +try { if (argc != 2) { cout << "Usage:\n" << argv[0] << " script.scr"; return 1; } - string path = argv[1]; - FILE *f = fopen(path.c_str(), "rb"); - if (!f) - { - cout << "Cannot open the file: " << argv[1]; - return 2; - } - uint32_t size = 0; - uint32_t dummy = 0; - fread(&size, sizeof(uint32_t), 1, f); - fread(&size, sizeof(uint32_t), 1, f); - fread(&size, sizeof(uint32_t), 1, f); - fread(&dummy, sizeof(uint32_t), 1, f); - string buf(size, 0); - fread(&buf[0], size, 1, f); - fclose(f); - path += ".txt"; - f = fopen(path.c_str(), "w"); - if (!f) - { - cout << "Cannot open the file: " << argv[1]; - return 3; - } - const char *ptr = &buf[0]; - while (ptr < &buf[0] + size) - { - fprintf(f, "%s\n", ptr); - ptr += strlen(ptr) + 1; - } - fclose(f); + + std::string filename = argv[1]; + + // read + buffer b(readFile(filename)); + script s; + s.load(b); + auto str = s.get_text(); + + // write + filename += ".txt"; + std::ofstream ofile(filename); + if (ofile) + ofile << str; return 0; -} \ No newline at end of file +} +catch (std::exception &e) +{ + printf("error: %s\n", e.what()); + return 1; +} +catch (...) +{ + printf("error: unknown exception\n"); + return 1; +}