diff --git a/src/GUI/LoadFromTheFileWindow.cpp b/src/GUI/LoadFromTheFileWindow.cpp
index f07465d..88fd7ab 100644
--- a/src/GUI/LoadFromTheFileWindow.cpp
+++ b/src/GUI/LoadFromTheFileWindow.cpp
@@ -17,7 +17,7 @@ LoadFromTheFileWindow::LoadFromTheFileWindow(QWidget* parent) : QWidget(parent)
QPushButton* btnCancel = new QPushButton(tr("BACK"));
QHBoxLayout* ltBtnOk = new QHBoxLayout();
QHBoxLayout* ltBtnCancel = new QHBoxLayout();
- QLabel* lblSelectFile = new QLabel(tr("Select .csf file:"));
+ QLabel* lblSelectFile = new QLabel(tr("Select .csf or .big file:"));
btnOk->setObjectName(nameof(btnOk));
btnOk->setFixedWidth(80);
@@ -47,7 +47,7 @@ LoadFromTheFileWindow::LoadFromTheFileWindow(QWidget* parent) : QWidget(parent)
QFileDialog* fileDialog = new QFileDialog(); // dialog for selecting the path to the file
fileDialog->setFileMode(QFileDialog::FileMode::ExistingFile);
fileDialog->setAcceptMode(QFileDialog::AcceptMode::AcceptOpen);
- fileDialog->setNameFilters({tr("Binary files") + " (*.csf)",
+ fileDialog->setNameFilters({tr("Binary files") + " (*.csf, *.big)",
tr("Any files") + " (*)"});
connect(fileDialog, &QFileDialog::fileSelected, lneFilePath, &QLineEdit::setText);
diff --git a/src/GUI/SetUpWindowsWrapper.cpp b/src/GUI/SetUpWindowsWrapper.cpp
index cd40361..3563c61 100644
--- a/src/GUI/SetUpWindowsWrapper.cpp
+++ b/src/GUI/SetUpWindowsWrapper.cpp
@@ -125,16 +125,22 @@ void SetUpWindowsWrapper::LoadFromTheGameWindow_AcceptConfiguration()
// TODO: Make it load vanila Generals
// Also as work with non-ascii paths
// Also as search in big-archives (see more at GZH source code)
- QString path = QString::fromStdString(Registry::GetPathToGame(Registry::Games::GeneralsZeroHour)) + "Data\\English\\generals.csf";
-
- if (!QFile::exists(path))
+ QString gamePath = QString::fromStdString(Registry::GetPathToGame(Registry::Games::GeneralsZeroHour));
+ QString pathDataEngGenCsf = gamePath + "Data\\English\\generals.csf";
+ QString pathEngBig = gamePath + "\\EnglishZH.big";
+
+ if (!QFile::exists(pathDataEngGenCsf) && !QFile::exists(pathEngBig))
{
- QMessageBox::critical(nullptr, L10N(PROGRAM_CONSTANTS->CSF_ERROR_HEADER),
- L10N(PROGRAM_CONSTANTS->CSF_EMPTY_DATA_ENGLISH));
+ QMessageBox::critical(nullptr, L10N(PROGRAM_CONSTANTS->GMFILES_SRCH_ERR_HEADER),
+ L10N(PROGRAM_CONSTANTS->BIG_NO_ENGLISH_ZH).arg(pathEngBig));
return;
}
+
+ if (QFile::exists(pathDataEngGenCsf))
+ WINDOW_MANAGER->SetCSFFilePath(pathDataEngGenCsf);
+ else
+ WINDOW_MANAGER->SetCSFFilePath(pathEngBig);
- WINDOW_MANAGER->SetCSFFilePath(path);
WINDOW_MANAGER->StartUpWindow_AcceptConfiguration();
}
diff --git a/src/GUI/Translations/ru.ts b/src/GUI/Translations/ru.ts
index d694be5..656bb62 100644
--- a/src/GUI/Translations/ru.ts
+++ b/src/GUI/Translations/ru.ts
@@ -40,89 +40,89 @@
File
- Файл
+ Файл
Open
- Открыть
+ Открыть
Save
- Сохранить
+ Сохранить
Save As...
- Сохранить как...
+ Сохранить как...
Special
- Дополнительно
+ Дополнительно
View
- Вид
+ Вид
Status Bar
- Строка состояния
+ Строка состояния
Enable
- Включить
+ Включить
Disable
- Отключить
+ Отключить
Settings
- Настройки
+ Настройки
About
- О программе
+ О программе
Layout %1
- Раскладка %1
+ Раскладка %1
Authors:
- Авторы:
+ Авторы:
Version:
- Версия:
+ Версия:
Program licensed with
- Программа лицензирована под
+ Программа лицензирована под
GitHub repository:
- Репозиторий на GitHub:
+ Репозиторий на GitHub:
Support development:
- Поддержать разработку:
+ Поддержать разработку:
@@ -160,109 +160,6 @@
ЯЗЫК
-
- HotkeysMainWindow
-
- File
- Файл
-
-
- Open
- Открыть
-
-
- Save
- Сохранить
-
-
- Save As...
- Сохранить как...
-
-
- Special
- Дополнительно
-
-
- View
- Вид
-
-
- Status Bar
- Строка состояния
-
-
- Enable
- Включить
-
-
- Disable
- Отключить
-
-
- Settings
- Настройки
-
-
- Language
- Язык
-
-
- About
- О программе
-
-
- Layout %1
- Раскладка %1
-
-
- Authors:
- Авторы:
-
-
- Version:
- Версия:
-
-
- Program licensed with
- Программа лицензирована под
-
-
- GitHub repository:
- Репозиторий на GitHub:
-
-
- Support development:
- Поддержать разработку:
-
-
- Lanugage
- Язык
-
-
- LANGUAGE
- ЯЗЫК
-
-
- OK
- Ок
-
-
- Cancel
- Отмена
-
-
- Program licensed by GNU GPL v3
- Программа лицензирована под лицензией GNU GPL v3
-
-
- GitHub Repository
- Репозиторий на GitHub
-
-
- <a href="https://github.com/MahBoiDeveloper/GZHHotkeysEditor">GitHub Repository</a>
- <a href="https://github.com/MahBoiDeveloper/GZHHotkeysEditor">Репозиторий на GitHub</a>
-
-
LoadFromTheFileWindow
@@ -280,9 +177,13 @@
Текстовые файлы
-
Select .csf file:
- Выберите .csf файл:
+ Выберите .csf файл:
+
+
+
+ Select .csf or .big file:
+ Выберите .csf или .big файл:
@@ -352,17 +253,17 @@
Возникла неизвестная ошибка
-
+
Error with CSF file
Ошибка с CSF файлом
-
+
Cannot process the empty file.
Невозможно обработать пустой файл.
-
+
Unable to find selected CSF file.
Невозможно найти указанный CSF файл.
@@ -373,7 +274,7 @@ Make sure that you are load correct file.
Проверьте, что вы загружаете правильный файл.
-
+
Choosen CSF file doesn't have CONTROLBAR category. Make sure that you are load correct file.
У выбранного CSF файла отсутствует категория CONTROLBAR. Проверьте, что вы загружаете правильный файл.
@@ -386,32 +287,51 @@ Make sure that you are load correct file.
Невозможно найти "generals.csf" в папке "Game/Data/English".
-
+
Choosen CSF file doesn't have OBJECT category. Make sure that you are load correct file.
У выбранного CSF файла отсутствует категория OBJECT. Проверьте, что вы загружаете правильный файл.
-
Unable find "generals.csf" file in "Game/Data/English" folder.
- Невозможно найти "generals.csf" в папке "Game/Data/English".
+ Невозможно найти "generals.csf" в папке "Game/Data/English".
+
+
+
+ Unable to find "generals.csf" file in "%1" folder.
+ Невозможно найти "generals.csf" в папке "%1".
+
+
+
+ Unable to find CSF file inside BIG archive "%1"
+ Невозможно найти CSF файл внутри BIG архива "%1"
+
+
+
+ Game files search error
+ Ошибка поиска по игровым файлам
+
+
+
+ Unable to find "EnglishZH.big" archive in "%1" folder.
+ Невозможно найти "EnglishZH.big" в папке "%1".
-
+
Buildings
Здания
-
+
Infantry
Пехота
-
+
Vehicles
Техника
-
+
Aircrafts
Авиация
diff --git a/src/GUI/WindowManager.cpp b/src/GUI/WindowManager.cpp
index da1ade2..70d472b 100644
--- a/src/GUI/WindowManager.cpp
+++ b/src/GUI/WindowManager.cpp
@@ -7,6 +7,7 @@
#include "../Unsorted.hpp"
#include "../Convert.hpp"
#include "../Registry.hpp"
+#include "../Exception.hpp"
#include "ImageManager.hpp"
#include "WindowManager.hpp"
@@ -56,7 +57,17 @@ void WindowManager::StartUpWindow_AcceptConfiguration()
return;
}
- CSF_PARSER = std::make_unique(strCSFFilePath);
+ try
+ {
+ CSF_PARSER = std::make_unique(strCSFFilePath);
+ }
+ catch(const Exception& e)
+ {
+ QMessageBox::critical(nullptr, L10N(PROGRAM_CONSTANTS->CSF_ERROR_HEADER),
+ e.what());
+ return;
+ }
+
if (!CSF_PARSER->ExistCategory(PROGRAM_CONSTANTS->HOTKEY_CSF_CATEGORY))
{
diff --git a/src/Parsers/CSFParser.cpp b/src/Parsers/CSFParser.cpp
index c5b836e..daa4d20 100644
--- a/src/Parsers/CSFParser.cpp
+++ b/src/Parsers/CSFParser.cpp
@@ -1,3 +1,6 @@
+#include
+#include
+
#include "../Logger.hpp"
#include "../Convert.hpp"
#include "../Unsorted.hpp"
@@ -17,20 +20,46 @@ using namespace std;
#pragma region Parsing
void CSFParser::Parse(const char* strFilePath)
{
- Path = QString(strFilePath).toStdWString();
- ifstream csfFile(Path.c_str(), ios::binary | ios::in);
- LOGMSG("Attempt to read binary file \"" + Path.c_str() + "\"...");
+ Path = QString(strFilePath).toUpper().toStdWString();
+ ifstream file(Path.c_str(), ios::binary | ios::in);
- if (csfFile.is_open())
+ if (file.is_open())
{
- ReadHeader(&csfFile);
- ReadBody(&csfFile);
+ if (Path.ends_with(L".BIG"))
+ {
+ LOGMSG("BIG archive detected. Try to find CSF file inside...");
+
+ bool searchResult = false;
+ char fourC[4] = {' ', ' ', ' ', ' '};
+ std::streampos fourCharOffset = sizeof(char) * 4;
+
+ while (!searchResult && file.good())
+ {
+ file.read(fourC, fourCharOffset);
+ searchResult = (fourC[0] == FSC[0]) && (fourC[1] == FSC[1]) && (fourC[2] == FSC[2]) && (fourC[3] == FSC[3]);
+ }
+
+ if (!file.good())
+ {
+ LOGMSG(PROGRAM_CONSTANTS->CSF_NO_CSF_IN_BIG.arg(Path));
+ throw Exception(L10N(PROGRAM_CONSTANTS->CSF_NO_CSF_IN_BIG).arg(Path));
+ }
+
+ auto offset = file.tellg();
+ file.clear();
+ file.seekg(offset - fourCharOffset);
+
+ LOGMSG("CSF file data found at offset : " + reinterpret_cast(offset));
+ }
+ LOGMSG("Attempt to read string table from \"" + Path.c_str() + "\" file...");
+ ReadHeader(&file);
+ ReadBody(&file);
LOGMSG("File \"" + Path.c_str() + "\" has been parsed; strings count : " + Table.size());
}
else
{
- throw Exception(QString("") + "Bad file name; unable to open file \"" + Path + "\"");
+ throw Exception(QString("") + "Bad file name error; unable to open file \"" + Path + "\"");
}
}
void CSFParser::Parse(const wstring& filePath) { Parse(filePath.c_str()); }
diff --git a/src/Parsers/CSFParser.hpp b/src/Parsers/CSFParser.hpp
index 1390e5a..0d0f50a 100644
--- a/src/Parsers/CSFParser.hpp
+++ b/src/Parsers/CSFParser.hpp
@@ -2,9 +2,7 @@
#include
#include
#include
-#include
#include
-#include
#define CSF_PARSER CSFParser::Instance
diff --git a/src/ProgramConstants.hpp b/src/ProgramConstants.hpp
index 21c43a6..b279a1a 100644
--- a/src/ProgramConstants.hpp
+++ b/src/ProgramConstants.hpp
@@ -26,62 +26,68 @@ class ProgramConstants
std::unique_ptr pSettingsFile = nullptr;
// Folders
- const QString RESOURCE_FOLDER = "Resources";
- const QString BINARIES_FOLDER = RESOURCE_FOLDER + "\\Binaries";
- const QString TRANSLATIONS_FOLDER = RESOURCE_FOLDER + "/Translations";
- const QString ICONS_FOLDER = RESOURCE_FOLDER + "/Icons";
- const QString THEME_FOLDER = RESOURCE_FOLDER + "/Theme";
- const QString QT_ICONS_FOLDER = ":/icons";
+ const QString RESOURCE_FOLDER = "Resources";
+ const QString BINARIES_FOLDER = RESOURCE_FOLDER + "\\Binaries";
+ const QString TRANSLATIONS_FOLDER = RESOURCE_FOLDER + "/Translations";
+ const QString ICONS_FOLDER = RESOURCE_FOLDER + "/Icons";
+ const QString THEME_FOLDER = RESOURCE_FOLDER + "/Theme";
+ const QString QT_ICONS_FOLDER = ":/icons";
// Resource files
- const QString TECH_TREE_FILE = RESOURCE_FOLDER + "/TechTree.json";
- const QString SETTINGS_FILE = RESOURCE_FOLDER + "/Settings.json";
- const QString STYLES_SHEET_FILE = THEME_FOLDER + "/Styles.css";
+ const QString TECH_TREE_FILE = RESOURCE_FOLDER + "/TechTree.json";
+ const QString SETTINGS_FILE = RESOURCE_FOLDER + "/Settings.json";
+ const QString STYLES_SHEET_FILE = THEME_FOLDER + "/Styles.css";
// Build-in files
- const QString MISSING_ICON_FILE = QT_ICONS_FOLDER + "/NoImageSmall.webp";
- const QString EDITOR_ICON_FILE = QT_ICONS_FOLDER + "/EditorIconSmall.webp";
- const QString EDITOR_BIG_ICON_FILE = QT_ICONS_FOLDER + "/EditorIconBig.webp";
- const QString GEARS_ICON_FILE = QT_ICONS_FOLDER + "/Gears.webp";
+ const QString MISSING_ICON_FILE = QT_ICONS_FOLDER + "/NoImageSmall.webp";
+ const QString EDITOR_ICON_FILE = QT_ICONS_FOLDER + "/EditorIconSmall.webp";
+ const QString EDITOR_BIG_ICON_FILE = QT_ICONS_FOLDER + "/EditorIconBig.webp";
+ const QString GEARS_ICON_FILE = QT_ICONS_FOLDER + "/Gears.webp";
// Window titles
- const QString COMMON_TITLE = "C&C: Generals Zero Hour Hotkey Editor";
- const QString SHORT_COMMON_TITLE = "C&C: GZH Hotkey Editor";
- const QString EDITOR_TITLE = SHORT_COMMON_TITLE + " — Editor";
- const QString LOAD_TITLE = SHORT_COMMON_TITLE + " — Load";
- const QString CREATE_TITLE = SHORT_COMMON_TITLE + " — New Set Up";
+ const QString COMMON_TITLE = "C&C: Generals Zero Hour Hotkey Editor";
+ const QString SHORT_COMMON_TITLE = "C&C: GZH Hotkey Editor";
+ const QString EDITOR_TITLE = SHORT_COMMON_TITLE + " — Editor";
+ const QString LOAD_TITLE = SHORT_COMMON_TITLE + " — Load";
+ const QString CREATE_TITLE = SHORT_COMMON_TITLE + " — New Set Up";
// Magic numbers that become known
- const double START_WIDGET_SIZE_RATIO = 3./7.;
- const QSize START_BUTTON_SIZE = QSize(230, 110);
- const QSize LANGUAGE_CHANGE_SIZE = QSize(250, 100);
- const QSize SET_UP_WINDOW_SIZE = QSize(795, 440);
- const int ICON_MIN_HEIGHT = 80;
- const int ICON_SCALING_HEIGHT = 25;
- const int KEYBOARD_KEY_WIDTH = 50;
- const int EMPTY_KEY_WIDTH = 25;
-
- // Errors
- const char* SETTINGS_NO_FOUND = "Unable to find \"Settings.json\" in \"Resource\" folder.";
- const char* TECH_TREE_NO_FOUND = "Unable to find \"TechTree.json\" in \"Resource\" folder.";
- const char* THEME_FOLDER_NO_FOUND = "Unable to find \"Resource/Theme\" folder.";
- const char* ICONS_FOLDER_NO_FOUND = "Unable to find \"Resource/Icons\" folder.";
- const char* TRANSLATIONS_NO_FOUND = "Unable to find \"Resource/Translations\" folder.";
- const char* UNKNOWN_ERROR = "Unknown error has been occured.";
-
- const QString CSF_ERROR_HEADER = QObject::tr("Error with CSF file");
- const QString CSF_EMPTY_STRING_ERROR = QObject::tr("Cannot process the empty file.");
- const QString CSF_DOESNT_EXIST_ERROR = QObject::tr("Unable to find selected CSF file.");
- const QString CSF_NO_CTLBAR_ERROR = QObject::tr("Choosen CSF file doesn't have CONTROLBAR category. Make sure that you are load correct file.");
- const QString CSF_NO_OBJECT_ERROR = QObject::tr("Choosen CSF file doesn't have OBJECT category. Make sure that you are load correct file.");
- const QString CSF_EMPTY_DATA_ENGLISH = QObject::tr("Unable find \"generals.csf\" file in \"Game/Data/English\" folder.");
-
- // Other constants
- const QString HOTKEY_CSF_CATEGORY = "CONTROLBAR";
- const QString OBJECT_CSF_CATEGORY = "OBJECT";
- const QVector GLA_SHORT_NAMES = {"GLA", "TOX", "STL", "DML"};
- const QVector USA_SHORT_NAMES = {"USA", "SWG", "AIR", "LSR"};
- const QVector PRC_SHORT_NAMES = {"PRC", "TNK", "INF", "NUK"};
+ const double START_WIDGET_SIZE_RATIO = 3./7.;
+ const QSize START_BUTTON_SIZE = QSize(230, 110);
+ const QSize LANGUAGE_CHANGE_SIZE = QSize(250, 100);
+ const QSize SET_UP_WINDOW_SIZE = QSize(795, 440);
+ const int ICON_MIN_HEIGHT = 80;
+ const int ICON_SCALING_HEIGHT = 25;
+ const int KEYBOARD_KEY_WIDTH = 50;
+ const int EMPTY_KEY_WIDTH = 25;
+
+ // Error strings
+ const char* SETTINGS_NO_FOUND = "Unable to find \"Settings.json\" in \"Resource\" folder.";
+ const char* TECH_TREE_NO_FOUND = "Unable to find \"TechTree.json\" in \"Resource\" folder.";
+ const char* THEME_FOLDER_NO_FOUND = "Unable to find \"Resource/Theme\" folder.";
+ const char* ICONS_FOLDER_NO_FOUND = "Unable to find \"Resource/Icons\" folder.";
+ const char* TRANSLATIONS_NO_FOUND = "Unable to find \"Resource/Translations\" folder.";
+ const char* UNKNOWN_ERROR = "Unknown error has been occured.";
+
+ // Translated error strings
+ const QString CSF_ERROR_HEADER = QObject::tr("Error with CSF file");
+ const QString CSF_EMPTY_STRING_ERROR = QObject::tr("Cannot process the empty file.");
+ const QString CSF_DOESNT_EXIST_ERROR = QObject::tr("Unable to find selected CSF file.");
+ const QString CSF_NO_CTLBAR_ERROR = QObject::tr("Choosen CSF file doesn't have CONTROLBAR category. Make sure that you are load correct file.");
+ const QString CSF_NO_OBJECT_ERROR = QObject::tr("Choosen CSF file doesn't have OBJECT category. Make sure that you are load correct file.");
+ const QString CSF_EMPTY_DATA_ENGLISH = QObject::tr("Unable to find \"generals.csf\" file in \"%1\" folder.");
+ const QString CSF_NO_CSF_IN_BIG = QObject::tr("Unable to find CSF file inside BIG archive \"%1\"");
+ const QString GMFILES_SRCH_ERR_HEADER = QObject::tr("Game files search error");
+ const QString BIG_NO_ENGLISH_ZH = QObject::tr("Unable to find \"EnglishZH.big\" archive in \"%1\" folder.");
+
+ // Other string constants
+ const QString HOTKEY_CSF_CATEGORY = "CONTROLBAR";
+ const QString OBJECT_CSF_CATEGORY = "OBJECT";
+
+ // Constant containers
+ const QVector GLA_SHORT_NAMES = {"GLA", "TOX", "STL", "DML"};
+ const QVector USA_SHORT_NAMES = {"USA", "SWG", "AIR", "LSR"};
+ const QVector PRC_SHORT_NAMES = {"PRC", "TNK", "INF", "NUK"};
const QSet DEFAULT_ALLOWED_KEYS =
{