diff --git a/src/Arguments.cpp b/src/Arguments.cpp index f24fc10..5d19d61 100644 --- a/src/Arguments.cpp +++ b/src/Arguments.cpp @@ -159,10 +159,12 @@ Arguments::Arguments() : QCoreApplication::translate( "Arguments", "\nList of available commands:\n" - " export Export files from FS archive\n" - " import Import files to FS archive\n" + " unpack Unpack files from FS archive\n" + " pack Pack files from directory to FS archive\n" + " export-texts Export texts to CSV from FIELD FS archive\n" + " import-texts Import texts from a CSV file to existing FIELD FS archive\n" "\n" - "\"%1 export --help\" to see help of the specific subcommand" + "\"%1 unpack --help\" to see help of the specific subcommand" ).arg(QFileInfo(qApp->arguments().first()).fileName()) ); @@ -182,10 +184,14 @@ void Arguments::parse() const QString &command = args.first(); - if (command == "export") { + if (command == "export-texts") { _command = Export; - } else if (command == "import") { + } else if (command == "import-texts") { _command = Import; + } else if (command == "unpack") { + _command = Unpack; + } else if (command == "pack") { + _command = Pack; } else { qWarning() << qPrintable(QCoreApplication::translate("Arguments", "Unknown command type:")) << qPrintable(command); return; diff --git a/src/Arguments.h b/src/Arguments.h index 8635055..3435777 100644 --- a/src/Arguments.h +++ b/src/Arguments.h @@ -63,7 +63,9 @@ class Arguments : public HelpArguments enum Command { None, Export, - Import + Import, + Unpack, + Pack }; Arguments(); inline Command command() const { diff --git a/src/ArgumentsExport.cpp b/src/ArgumentsExport.cpp index f8d9b4f..f6a87fd 100644 --- a/src/ArgumentsExport.cpp +++ b/src/ArgumentsExport.cpp @@ -18,18 +18,18 @@ ArgumentsExport::ArgumentsExport() : CommonArguments() { - _ADD_FLAG(_OPTION_NAMES("r", "recursive"), - "Extract FS archives recursively."); + _ADD_FLAG(_OPTION_NAMES("f", "force"), + "Overwrite destination file if exists."); - _parser.addPositionalArgument("file", QCoreApplication::translate("ArgumentsExport", "Input file or directory.")); - _parser.addPositionalArgument("directory", QCoreApplication::translate("ArgumentsExport", "Output directory.")); + _parser.addPositionalArgument("archive", QCoreApplication::translate("ArgumentsExport", "Input Field FS archive.")); + _parser.addPositionalArgument("output", QCoreApplication::translate("ArgumentsExport", "Output CSV file path.")); parse(); } -bool ArgumentsExport::recursive() const +bool ArgumentsExport::force() const { - return _parser.isSet("recursive"); + return _parser.isSet("force"); } void ArgumentsExport::parse() @@ -44,16 +44,15 @@ void ArgumentsExport::parse() QStringList paths = wilcardParse(); if (paths.size() == 2) { - // Output directory - if (QDir(paths.last()).exists()) { - _directory = paths.takeLast(); - } else { + // Output file + _destination = paths.takeLast(); + + if (!_parser.isSet("force") && QFile::exists(_destination)) { qWarning() << qPrintable( - QCoreApplication::translate("Arguments", "Error: target directory does not exist:")) - << qPrintable(paths.last()); + QCoreApplication::translate("Arguments", "Error: target file already exist, use --force to override the file")); exit(1); } - + if (!paths.isEmpty()) { _path = paths.first(); } diff --git a/src/ArgumentsExport.h b/src/ArgumentsExport.h index 4082afc..09a11ec 100644 --- a/src/ArgumentsExport.h +++ b/src/ArgumentsExport.h @@ -23,11 +23,11 @@ class ArgumentsExport : public CommonArguments { public: ArgumentsExport(); - bool recursive() const; + bool force() const; inline QString destination() const { - return _directory; + return _destination; } private: void parse(); - QString _directory; + QString _destination; }; diff --git a/src/ArgumentsImport.cpp b/src/ArgumentsImport.cpp index 398f34e..d32293b 100644 --- a/src/ArgumentsImport.cpp +++ b/src/ArgumentsImport.cpp @@ -18,49 +18,31 @@ ArgumentsImport::ArgumentsImport() : CommonArguments() { - _ADD_FLAG(_OPTION_NAMES("f", "force"), - "Overwrite destination file if exists."); - _ADD_ARGUMENT(_OPTION_NAMES("c", "compression"), "Compression format ([lzs], lz4, none).", "compression-format", "lzs"); - _ADD_ARGUMENT("prefix", "Custom directory prefix inside the target archive (default \"c:\\ff8\\data\\\")", "prefix", "c:\\ff8\\data\\"); + _ADD_FLAG(_OPTION_NAMES("c", "column"), + "Column (starting at 1) to use as text (default=2)."); - _parser.addPositionalArgument("directory", QCoreApplication::translate("ArgumentsImport", "Input directory.")); - _parser.addPositionalArgument("file", QCoreApplication::translate("ArgumentsImport", "Input file or directory.")); + _parser.addPositionalArgument("archive", QCoreApplication::translate("ArgumentsImport", "Input Field FS archive.")); + _parser.addPositionalArgument("file", QCoreApplication::translate("ArgumentsImport", "Input CSV file path.")); parse(); } -bool ArgumentsImport::force() const +int ArgumentsImport::column() const { - return _parser.isSet("force"); -} - -QString ArgumentsImport::prefix() const -{ - QString pre = _parser.value("prefix"); - - if (pre.isEmpty()) { - return "c:\\ff8\\data\\"; + if (!_parser.isSet("column")) { + return 2; } - return pre; -} - -FiCompression ArgumentsImport::compressionFormat() const -{ - QString compression = _parser.value("compression"); - if (compression.isEmpty() || compression.toLower() == "lzs") { - return FiCompression::CompressionLzs; - } - if (compression.toLower() == "lz4") { - return FiCompression::CompressionLz4; - } - if (compression.toLower() == "none") { - return FiCompression::CompressionNone; + bool ok = false; + int ret = _parser.value("column").toInt(&ok); + + if (!ok || ret <= 0) { + qWarning() << qPrintable( + QCoreApplication::translate("Arguments", "Error: column should be an integer value >= 1")); + exit(1); } - qWarning() << qPrintable( - QCoreApplication::translate("Arguments", "Error: unknown compression, available values: lzs, lz4, none")); - exit(1); + return ret; } void ArgumentsImport::parse() @@ -77,7 +59,7 @@ void ArgumentsImport::parse() if (paths.size() == 2) { // Source directory if (QDir(paths.first()).exists()) { - _directory = paths.takeFirst(); + _destination = paths.takeFirst(); } else { qWarning() << qPrintable( QCoreApplication::translate("Arguments", "Error: source directory does not exist:")) diff --git a/src/ArgumentsImport.h b/src/ArgumentsImport.h index 0cafc03..52f92de 100644 --- a/src/ArgumentsImport.h +++ b/src/ArgumentsImport.h @@ -24,13 +24,11 @@ class ArgumentsImport : public CommonArguments { public: ArgumentsImport(); - bool force() const; - FiCompression compressionFormat() const; - QString prefix() const; + int column() const; inline QString source() const { - return _directory; + return _destination; } private: void parse(); - QString _directory; + QString _destination; }; diff --git a/src/ArgumentsPack.cpp b/src/ArgumentsPack.cpp new file mode 100644 index 0000000..22000e4 --- /dev/null +++ b/src/ArgumentsPack.cpp @@ -0,0 +1,93 @@ +/**************************************************************************** + ** Copyright (C) 2009-2021 Arzel Jérôme + ** + ** 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 . + ****************************************************************************/ +#include "ArgumentsPack.h" + +ArgumentsPack::ArgumentsPack() : CommonArguments() +{ + _ADD_FLAG(_OPTION_NAMES("f", "force"), + "Overwrite destination file if exists."); + _ADD_ARGUMENT(_OPTION_NAMES("c", "compression"), "Compression format ([lzs], lz4, none).", "compression-format", "lzs"); + _ADD_ARGUMENT("prefix", "Custom directory prefix inside the target archive (default \"c:\\ff8\\data\\\")", "prefix", "c:\\ff8\\data\\"); + + _parser.addPositionalArgument("directory", QCoreApplication::translate("ArgumentsPack", "Input directory.")); + _parser.addPositionalArgument("file", QCoreApplication::translate("ArgumentsPack", "Input file or directory.")); + + parse(); +} + +bool ArgumentsPack::force() const +{ + return _parser.isSet("force"); +} + +QString ArgumentsPack::prefix() const +{ + QString pre = _parser.value("prefix"); + + if (pre.isEmpty()) { + return "c:\\ff8\\data\\"; + } + + return pre; +} + +FiCompression ArgumentsPack::compressionFormat() const +{ + QString compression = _parser.value("compression"); + if (compression.isEmpty() || compression.toLower() == "lzs") { + return FiCompression::CompressionLzs; + } + if (compression.toLower() == "lz4") { + return FiCompression::CompressionLz4; + } + if (compression.toLower() == "none") { + return FiCompression::CompressionNone; + } + + qWarning() << qPrintable( + QCoreApplication::translate("Arguments", "Error: unknown compression, available values: lzs, lz4, none")); + exit(1); +} + +void ArgumentsPack::parse() +{ + _parser.process(*qApp); + + if (_parser.positionalArguments().size() > 3) { + qWarning() << qPrintable( + QCoreApplication::translate("Arguments", "Error: too much parameters")); + exit(1); + } + + QStringList paths = wilcardParse(); + if (paths.size() == 2) { + // Source directory + if (QDir(paths.first()).exists()) { + _directory = paths.takeFirst(); + } else { + qWarning() << qPrintable( + QCoreApplication::translate("Arguments", "Error: source directory does not exist:")) + << qPrintable(paths.first()); + exit(1); + } + + if (!paths.isEmpty()) { + _path = paths.first(); + } + } + mapNamesFromFiles(); +} diff --git a/src/ArgumentsPack.h b/src/ArgumentsPack.h new file mode 100644 index 0000000..bd4c58f --- /dev/null +++ b/src/ArgumentsPack.h @@ -0,0 +1,36 @@ +/**************************************************************************** + ** Copyright (C) 2009-2021 Arzel Jérôme + ** + ** 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 "Arguments.h" +#include "FsArchive.h" + +class ArgumentsPack : public CommonArguments +{ +public: + ArgumentsPack(); + bool force() const; + FiCompression compressionFormat() const; + QString prefix() const; + inline QString source() const { + return _directory; + } +private: + void parse(); + QString _directory; +}; diff --git a/src/ArgumentsUnpack.cpp b/src/ArgumentsUnpack.cpp new file mode 100644 index 0000000..a24366e --- /dev/null +++ b/src/ArgumentsUnpack.cpp @@ -0,0 +1,62 @@ +/**************************************************************************** + ** Copyright (C) 2009-2021 Arzel Jérôme + ** + ** 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 . + ****************************************************************************/ +#include "ArgumentsUnpack.h" + +ArgumentsUnpack::ArgumentsUnpack() : CommonArguments() +{ + _ADD_FLAG(_OPTION_NAMES("r", "recursive"), + "Extract FS archives recursively."); + + _parser.addPositionalArgument("file", QCoreApplication::translate("ArgumentsUnpack", "Input file or directory.")); + _parser.addPositionalArgument("directory", QCoreApplication::translate("ArgumentsUnpack", "Output directory.")); + + parse(); +} + +bool ArgumentsUnpack::recursive() const +{ + return _parser.isSet("recursive"); +} + +void ArgumentsUnpack::parse() +{ + _parser.process(*qApp); + + if (_parser.positionalArguments().size() > 3) { + qWarning() << qPrintable( + QCoreApplication::translate("Arguments", "Error: too much parameters")); + exit(1); + } + + QStringList paths = wilcardParse(); + if (paths.size() == 2) { + // Output directory + if (QDir(paths.last()).exists()) { + _directory = paths.takeLast(); + } else { + qWarning() << qPrintable( + QCoreApplication::translate("Arguments", "Error: target directory does not exist:")) + << qPrintable(paths.last()); + exit(1); + } + + if (!paths.isEmpty()) { + _path = paths.first(); + } + } + mapNamesFromFiles(); +} diff --git a/src/ArgumentsUnpack.h b/src/ArgumentsUnpack.h new file mode 100644 index 0000000..0c394d3 --- /dev/null +++ b/src/ArgumentsUnpack.h @@ -0,0 +1,33 @@ +/**************************************************************************** + ** Copyright (C) 2009-2021 Arzel Jérôme + ** + ** 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 "Arguments.h" + +class ArgumentsUnpack : public CommonArguments +{ +public: + ArgumentsUnpack(); + bool recursive() const; + inline QString destination() const { + return _directory; + } +private: + void parse(); + QString _directory; +}; diff --git a/src/CLI.cpp b/src/CLI.cpp index 226799a..9036614 100644 --- a/src/CLI.cpp +++ b/src/CLI.cpp @@ -19,9 +19,13 @@ #include "Arguments.h" #include "ArgumentsExport.h" #include "ArgumentsImport.h" +#include "ArgumentsUnpack.h" +#include "ArgumentsPack.h" #include "FsArchive.h" +#include "TextExporter.h" #include "LZS.h" #include "QLZ4.h" +#include "FieldArchivePC.h" #include #include @@ -62,6 +66,58 @@ void CLI::commandExport() return; } + FieldArchivePC fieldArchive; + if (fieldArchive.open(args.path(), &observer) != 0) { + qWarning() << fieldArchive.errorMessage(); + return; + } + QStringList langs = fieldArchive.languages(); + + TextExporter exporter(&fieldArchive); + + if (!exporter.toCsv(args.destination(), langs, QChar(','), QChar('"'), CsvFile::Utf8, &observer) && !observer.observerWasCanceled()) { + return; + } +} + +void CLI::commandImport() +{ + ArgumentsImport args; + if (args.help() || args.source().isEmpty()) { + args.showHelp(); + } + FsArchive *archive = openArchive(args.inputFormat(), args.path()); + if (archive == nullptr) { + return; + } + + FieldArchivePC fieldArchive; + if (fieldArchive.open(args.path(), &observer) != 0) { + qWarning() << fieldArchive.errorMessage(); + return; + } + + TextExporter exporter(&fieldArchive); + if (!exporter.fromCsv(args.source(), args.column(), QChar(','), QChar('"'), CsvFile::Utf8, &observer) && !observer.observerWasCanceled()) { + return; + } + + fieldArchive.save(&observer); +} + + +void CLI::commandUnpack() +{ + ArgumentsUnpack args; + if (args.help() || args.destination().isEmpty()) { + args.showHelp(); + } + + FsArchive *archive = openArchive(args.inputFormat(), args.path()); + if (archive == nullptr) { + return; + } + QString commonPath = "c:\\ff8\\data\\"; QStringList fileList = archive->tocInDirectory(commonPath); QStringList selectedFiles = filteredFiles(fileList, args.includes(), args.excludes()); @@ -105,9 +161,9 @@ void CLI::commandExport() delete archive; } -void CLI::commandImport() +void CLI::commandPack() { - ArgumentsImport args; + ArgumentsPack args; if (args.help() || args.source().isEmpty()) { args.showHelp(); } @@ -274,5 +330,11 @@ void CLI::exec() case Arguments::Import: commandImport(); break; + case Arguments::Unpack: + commandUnpack(); + break; + case Arguments::Pack: + commandPack(); + break; } } diff --git a/src/CLI.h b/src/CLI.h index 848419f..52010cd 100644 --- a/src/CLI.h +++ b/src/CLI.h @@ -53,6 +53,8 @@ class CLI private: static void commandExport(); static void commandImport(); + static void commandUnpack(); + static void commandPack(); static FsArchive *openArchive(const QString &ext, const QString &path); static QStringList filteredFiles(const QStringList &fileList, const QStringList &includePatterns, const QStringList &excludePatterns); static CLIObserver observer; diff --git a/src/FF8Color.h b/src/FF8Color.h new file mode 100644 index 0000000..a2952ff --- /dev/null +++ b/src/FF8Color.h @@ -0,0 +1,37 @@ +/**************************************************************************** + ** Deling Final Fantasy VIII Field Editor + ** Copyright (C) 2009-2024 Arzel Jérôme + ** + ** 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 + +#define COEFF_COLOR 8.2258064516129032258064516129032 // 255/31 + +class FF8Color +{ +public: + static inline quint16 toPsColor(const QRgb &color) { + return (qRound(qRed(color)/COEFF_COLOR) & 31) | ((qRound(qGreen(color)/COEFF_COLOR) & 31) << 5) | ((qRound(qBlue(color)/COEFF_COLOR) & 31) << 10) | ((qAlpha(color)==255) << 15); + } + static inline QRgb fromPsColor(quint16 color, bool useAlpha = false) { + quint8 r = color & 31, + g = (color >> 5) & 31, + b = (color >> 10) & 31; + + return qRgba((r << 3) + (r >> 2), (g << 3) + (g >> 2), (b << 3) + (b >> 2), color == 0 && useAlpha ? 0 : 255); + } +}; diff --git a/src/FF8Image.cpp b/src/FF8Image.cpp index 738c162..e32ba13 100644 --- a/src/FF8Image.cpp +++ b/src/FF8Image.cpp @@ -17,6 +17,7 @@ ****************************************************************************/ #include "FF8Image.h" #include "LZS.h" +#include "FF8Color.h" QPixmap FF8Image::lzs(const QByteArray &data) { @@ -54,7 +55,7 @@ QPixmap FF8Image::lzs(const QByteArray &data) // if(color>>15) // image.setPixel(QPoint(x, y), qRgb(0, 255, 0)); // else - pixels[x + y*l] = fromPsColor(color); + pixels[x + y*l] = FF8Color::fromPsColor(color); ++x; if(x==l) @@ -84,7 +85,7 @@ QByteArray FF8Image::toLzs(const QImage &image, quint16 u1, quint16 u2) const QRgb *pixels = (QRgb *)image.constBits(); while(image.valid(x, y)) { - quint16 color = toPsColor(pixels[x + y * w]); + quint16 color = FF8Color::toPsColor(pixels[x + y * w]); data.append((char *)&color, 2); ++x; diff --git a/src/FF8Image.h b/src/FF8Image.h index 20fab8f..6ec2899 100644 --- a/src/FF8Image.h +++ b/src/FF8Image.h @@ -19,21 +19,9 @@ #include -#define COEFF_COLOR 8.2258064516129032258064516129032 // 255/31 - class FF8Image { public: - static inline quint16 toPsColor(const QRgb &color) { - return (qRound(qRed(color)/COEFF_COLOR) & 31) | ((qRound(qGreen(color)/COEFF_COLOR) & 31) << 5) | ((qRound(qBlue(color)/COEFF_COLOR) & 31) << 10) | ((qAlpha(color)==255) << 15); - } - static inline QRgb fromPsColor(quint16 color, bool useAlpha=false) { - quint8 r = color & 31, - g = (color >> 5) & 31, - b = (color >> 10) & 31; - - return qRgba((r << 3) + (r >> 2), (g << 3) + (g >> 2), (b << 3) + (b >> 2), color == 0 && useAlpha ? 0 : 255); - } static QPixmap lzs(const QByteArray &data); static QByteArray toLzs(const QImage &image, quint16 u1, quint16 u2); diff --git a/src/FieldArchive.h b/src/FieldArchive.h index a1ca7c1..39c3bfe 100644 --- a/src/FieldArchive.h +++ b/src/FieldArchive.h @@ -19,7 +19,7 @@ #include #include "files/JsmFile.h" -#include "Poly.h" +#include "Vertex.h" class Field; struct ArchiveObserver; diff --git a/src/FsDialog.cpp b/src/FsDialog.cpp index f963387..723e902 100644 --- a/src/FsDialog.cpp +++ b/src/FsDialog.cpp @@ -171,14 +171,20 @@ void FsDialog::generatePreview() { preview->imagePreview(QPixmap::fromImage(TdwFile::image(data, TdwFile::Color(currentPal))), fileName, currentPal, 8); } - else if (fileType == "map" || fileType == "mim") + else if (fileType == "map") { QString filePathWithoutExt = filePath.left(filePath.size()-3); BackgroundFile backgroundFile; - backgroundFile.open(fileType == "map" ? data : fsArchive->fileData(filePathWithoutExt+"map"), - fileType == "mim" ? data : fsArchive->fileData(filePathWithoutExt+"mim")); + backgroundFile.open(data, fsArchive->fileData(filePathWithoutExt+"mim")); preview->imagePreview(QPixmap::fromImage(backgroundFile.background()), fileName); } + else if (fileType == "mim") + { + QString filePathWithoutExt = filePath.left(filePath.size()-3); + BackgroundFile backgroundFile; + backgroundFile.open(fsArchive->fileData(filePathWithoutExt+"map"), data); + preview->imagePreview(QPixmap::fromImage(BackgroundFile::mimToImage(BackgroundFile::DepthColor)), fileName); + } else if (fileType == "cnf") { QStringDecoder decoder("Shift-JIS"); diff --git a/src/MainWindow.cpp b/src/MainWindow.cpp index 8ca1533..d1e9c13 100644 --- a/src/MainWindow.cpp +++ b/src/MainWindow.cpp @@ -41,6 +41,7 @@ #include "TextPreview.h" #include "ConfigDialog.h" #include "FieldThread.h" +#include "FF8Image.h" MainWindow::MainWindow() : fieldArchive(nullptr), field(nullptr), currentField(nullptr), @@ -882,7 +883,7 @@ void MainWindow::importAllTexts() TextExporter exporter(fieldArchive); - if (!exporter.fromCsv(path, dialog.column(), &progress) && !progress.observerWasCanceled()) { + if (!exporter.fromCsv(path, dialog.column(), QChar(','), QChar('"'), CsvFile::Utf8, &progress) && !progress.observerWasCanceled()) { QMessageBox::warning(this, tr("Erreur"), exporter.errorString()); } diff --git a/src/Poly.h b/src/Poly.h index 386fc9d..14d23d4 100644 --- a/src/Poly.h +++ b/src/Poly.h @@ -19,24 +19,7 @@ #include #include - -struct Vertex { - qint16 x, y, z; -}; - -inline bool operator==(const Vertex &v1, const Vertex &v2) -{ - return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z; -} - -inline size_t qHash(const Vertex &key, uint seed) -{ - return qHash(quint64(key.x | (key.y << 16)) | (quint64(key.z) << 32), seed); -} - -struct TexCoord { - quint8 x, y; -}; +#include "Vertex.h" class Poly { diff --git a/src/TextExporter.cpp b/src/TextExporter.cpp index 6ca20b8..bf65187 100644 --- a/src/TextExporter.cpp +++ b/src/TextExporter.cpp @@ -22,6 +22,7 @@ #include "ArchiveObserver.h" #include "files/MsdFile.h" #include "Config.h" +#include "FF8Text.h" TextExporter::TextExporter(FieldArchive *archive) : _archive(archive) @@ -130,7 +131,7 @@ bool TextExporter::toCsv(const QString &fileName, const QStringList &langs, QCha return true; } -bool TextExporter::fromCsv(const QString &fileName, quint8 column, ArchiveObserver *observer) +bool TextExporter::fromCsv(const QString &fileName, quint8 column, QChar fieldSeparator, QChar quoteCharacter, CsvFile::CsvEncoding encoding, ArchiveObserver *observer) { if (!_archive) { return false; @@ -147,7 +148,7 @@ bool TextExporter::fromCsv(const QString &fileName, quint8 column, ArchiveObserv return false; } - CsvFile csv(&io); + CsvFile csv(&io, fieldSeparator, quoteCharacter, encoding); const QStringList &mapList = _archive->mapList(); QStringList line; MsdFile *msd = nullptr; diff --git a/src/TextExporter.h b/src/TextExporter.h index ace6e8a..4e02210 100644 --- a/src/TextExporter.h +++ b/src/TextExporter.h @@ -28,7 +28,7 @@ class TextExporter public: explicit TextExporter(FieldArchive *archive); bool toCsv(const QString &fileName, const QStringList &langs, QChar fieldSeparator, QChar quoteCharacter, CsvFile::CsvEncoding encoding, ArchiveObserver *observer = nullptr); - bool fromCsv(const QString &fileName, quint8 column, ArchiveObserver *observer = nullptr); + bool fromCsv(const QString &fileName, quint8 column, QChar fieldSeparator, QChar quoteCharacter, CsvFile::CsvEncoding encoding, ArchiveObserver *observer = nullptr); inline const QString &errorString() const { return _lastErrorString; } diff --git a/src/TextPreview.cpp b/src/TextPreview.cpp index 5a4eefc..f3f95ca 100644 --- a/src/TextPreview.cpp +++ b/src/TextPreview.cpp @@ -17,7 +17,6 @@ ****************************************************************************/ #include "TextPreview.h" #include "FF8Text.h" -#include "FF8Image.h" #include "Data.h" #include "Config.h" #include "FF8Font.h" diff --git a/src/Vertex.h b/src/Vertex.h new file mode 100644 index 0000000..524648a --- /dev/null +++ b/src/Vertex.h @@ -0,0 +1,21 @@ +#pragma once + +#include + +struct Vertex { + qint16 x, y, z; +}; + +inline bool operator==(const Vertex &v1, const Vertex &v2) +{ + return v1.x == v2.x && v1.y == v2.y && v1.z == v2.z; +} + +inline size_t qHash(const Vertex &key, uint seed) +{ + return qHash(quint64(key.x | (key.y << 16)) | (quint64(key.z) << 32), seed); +} + +struct TexCoord { + quint8 x, y; +}; diff --git a/src/VertexWidget.h b/src/VertexWidget.h index 2b59b44..6817b79 100644 --- a/src/VertexWidget.h +++ b/src/VertexWidget.h @@ -18,7 +18,7 @@ #pragma once #include -#include "Poly.h" +#include "Vertex.h" class VertexWidget : public QWidget { diff --git a/src/files/BackgroundFile.cpp b/src/files/BackgroundFile.cpp index cd4810c..53a4fae 100644 --- a/src/files/BackgroundFile.cpp +++ b/src/files/BackgroundFile.cpp @@ -16,6 +16,8 @@ ** along with this program. If not, see . ****************************************************************************/ #include "files/BackgroundFile.h" +#include "FF8Color.h" +#include "FF8Image.h" QByteArray BackgroundFile::mim = QByteArray(); @@ -454,7 +456,7 @@ void BackgroundFile::BGcolor(quint16 value, quint8 blendType, QRgb *pixels, if (forceBlack) { color = 0; } else { - color = FF8Image::fromPsColor(value); + color = FF8Color::fromPsColor(value); } if (blendType == 4) { @@ -517,7 +519,7 @@ QImage BackgroundFile::mimToImage(MapDepth depth) quint16 color; memcpy(&color, data + 0x3000 + j*2, 2); - px[j] = FF8Image::fromPsColor(color); + px[j] = FF8Color::fromPsColor(color); } return img; diff --git a/src/files/BackgroundFile.h b/src/files/BackgroundFile.h index d27c320..1af909d 100644 --- a/src/files/BackgroundFile.h +++ b/src/files/BackgroundFile.h @@ -18,7 +18,7 @@ #pragma once #include "files/File.h" -#include "FF8Image.h" +#include // Please do not use bitfields here diff --git a/src/files/CaFile.h b/src/files/CaFile.h index fac2eea..2605500 100644 --- a/src/files/CaFile.h +++ b/src/files/CaFile.h @@ -18,7 +18,7 @@ #pragma once #include "files/File.h" -#include "Poly.h" +#include "Vertex.h" struct Camera { Vertex camera_axis[3]; diff --git a/src/files/IdFile.h b/src/files/IdFile.h index d3aaca8..ee3e29a 100644 --- a/src/files/IdFile.h +++ b/src/files/IdFile.h @@ -18,7 +18,7 @@ #pragma once #include "files/File.h" -#include "Poly.h" +#include "Vertex.h" struct Vertex_sr { qint16 x, y, z, res;// res = Triangle[0].z (padding) diff --git a/src/files/InfFile.h b/src/files/InfFile.h index 4f7138b..857af14 100644 --- a/src/files/InfFile.h +++ b/src/files/InfFile.h @@ -18,7 +18,7 @@ #pragma once #include "files/File.h" -#include "Poly.h" +#include "Vertex.h" struct Range { qint16 top; diff --git a/src/files/MskFile.h b/src/files/MskFile.h index b2bdbf2..9f93c14 100644 --- a/src/files/MskFile.h +++ b/src/files/MskFile.h @@ -18,7 +18,7 @@ #pragma once #include "files/File.h" -#include "Poly.h" +#include "Vertex.h" class MskFile : public File { diff --git a/src/files/PmpFile.cpp b/src/files/PmpFile.cpp index a2426d1..25613e8 100644 --- a/src/files/PmpFile.cpp +++ b/src/files/PmpFile.cpp @@ -16,7 +16,7 @@ ** along with this program. If not, see . ****************************************************************************/ #include "files/PmpFile.h" -#include "FF8Image.h" +#include "FF8Color.h" QString PmpFile::currentFieldName; @@ -77,7 +77,7 @@ QImage PmpFile::palette() const for(int i=0 ; i> 4)*2], 2); - px[j] = FF8Image::fromPsColor(color); + px[j] = FF8Color::fromPsColor(color); } return img; @@ -124,7 +124,7 @@ QImage PmpFile::image(quint8 deph, quint8 palID) const quint16 color; memcpy(&color, &constPmp[4 + (quint8)pmp.at(516 + j)*2], 2); - px[j] = FF8Image::fromPsColor(color); + px[j] = FF8Color::fromPsColor(color); } return img; @@ -142,7 +142,7 @@ QImage PmpFile::image(quint8 deph, quint8 palID) const quint16 color; memcpy(&color, &constPmp[516 + j*2], 2); - px[j] = FF8Image::fromPsColor(color); + px[j] = FF8Color::fromPsColor(color); } return img; diff --git a/src/files/PmpFile.h b/src/files/PmpFile.h index fd0d3b3..4714fdc 100644 --- a/src/files/PmpFile.h +++ b/src/files/PmpFile.h @@ -18,6 +18,7 @@ #pragma once #include "files/File.h" +#include class PmpFile : public File { diff --git a/src/files/TexFile.cpp b/src/files/TexFile.cpp index b8e3615..1233c56 100644 --- a/src/files/TexFile.cpp +++ b/src/files/TexFile.cpp @@ -16,7 +16,7 @@ ** along with this program. If not, see . ****************************************************************************/ #include "TexFile.h" -#include "FF8Image.h" +#include "FF8Color.h" TexFile::TexFile(const QByteArray &data) : TextureFile() @@ -108,7 +108,7 @@ bool TexFile::open(const QByteArray &data) for (i = 0; i < imageSectionSize; i+=header.bytesPerPixel) { if (header.bytesPerPixel == 2) { memcpy(&color, &constData[headerSize+i], 2); - pixels[i/2] = FF8Image::fromPsColor(color); + pixels[i/2] = FF8Color::fromPsColor(color); } else if (header.bytesPerPixel == 3) { pixels[i/3] = qRgb(constData[headerSize+i], constData[headerSize+i+1], constData[headerSize+i+2]); } else if (header.bytesPerPixel == 4) { @@ -176,7 +176,7 @@ bool TexFile::save(QByteArray &data) } else { QRgb *pixels = (QRgb *)_image.bits(); for (int i = 0; i < _image.width()*_image.height(); ++i) { - quint16 color = FF8Image::toPsColor(pixels[i]); + quint16 color = FF8Color::toPsColor(pixels[i]); data.append((char *)&color, 2); } diff --git a/src/files/TextureFile.cpp b/src/files/TextureFile.cpp index cab1361..9002248 100644 --- a/src/files/TextureFile.cpp +++ b/src/files/TextureFile.cpp @@ -16,7 +16,6 @@ ** along with this program. If not, see . ****************************************************************************/ #include "TextureFile.h" -#include "FF8Image.h" TextureFile::TextureFile() : File(), _currentColorTable(0) diff --git a/src/files/TimFile.cpp b/src/files/TimFile.cpp index 44c6f28..c6a0138 100644 --- a/src/files/TimFile.cpp +++ b/src/files/TimFile.cpp @@ -16,7 +16,7 @@ ** along with this program. If not, see . ****************************************************************************/ #include "TimFile.h" -#include "FF8Image.h" +#include "FF8Color.h" TimFile::TimFile(const QByteArray &data) : TextureFile(), palX(0), palY(0), palW(0), palH(0), imgX(0), imgY(0) @@ -83,7 +83,7 @@ bool TimFile::open(const QByteArray &data) for (quint16 j = 0; j < onePalSize; ++j) { memcpy(&color, &constData[20+pos*2+j*2], 2); - pal.append(FF8Image::fromPsColor(color, true)); + pal.append(FF8Color::fromPsColor(color, true)); } _colorTables.append(pal); @@ -184,7 +184,7 @@ bool TimFile::open(const QByteArray &data) while (i &colorTable: _colorTables) { int i; for (i = 0; i> &texs : qAsConst(_textures)) { - for (const QPair &tex : qAsConst(texs)) { + for (const QList> &texs : std::as_const(_textures)) { + for (const QPair &tex : std::as_const(texs)) { delete tex.first; } } @@ -293,10 +293,10 @@ void WorldmapGLWidget::importVertices() //_map->searchBlackPixels(images, seaImage, roadImage); if (_textures.empty()) { - for (const QList< QPair > &images : qAsConst(images)) { + for (const QList< QPair > &images : std::as_const(images)) { QList< QPair > texs; - for (const QPair &image : qAsConst(images)) { + for (const QPair &image : std::as_const(images)) { texs.append(qMakePair(textureFromImage(image.first), image.second)); }