Skip to content

Commit

Permalink
Adding cli command
Browse files Browse the repository at this point in the history
  • Loading branch information
myst6re committed Apr 19, 2024
1 parent 73ff15e commit b65605e
Show file tree
Hide file tree
Showing 9 changed files with 253 additions and 3 deletions.
2 changes: 2 additions & 0 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -358,6 +358,8 @@ set(PROJECT_CLI_SOURCES
"src/ArgumentsExport.h"
"src/ArgumentsPatch.cpp"
"src/ArgumentsPatch.h"
"src/ArgumentsTools.cpp"
"src/ArgumentsTools.h"
"src/CLI.cpp"
"src/CLI.h"
"src/Data.cpp"
Expand Down
7 changes: 5 additions & 2 deletions src/Arguments.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -155,8 +155,9 @@ Arguments::Arguments() :
QCoreApplication::translate(
"Arguments",
"\nList of available commands:\n"
" export Export various assets from archive to files\n"
" patch Patch archive\n"
" export Export various assets from archive to files\n"
" patch Patch archive\n"
" unpack-bg-mod Unpack background mod packed with Palmer\n"
"\n"
"\"%1 export --help\" to see help of the specific subcommand"
).arg(QFileInfo(qApp->arguments().first()).fileName())
Expand All @@ -182,6 +183,8 @@ void Arguments::parse()
_command = Export;
} else if (command == "patch") {
_command = Patch;
} else if (command == "unpack-bg-mod") {
_command = Tools;
} else {
qWarning() << qPrintable(QCoreApplication::translate("Arguments", "Unknown command type:")) << qPrintable(command);
return;
Expand Down
3 changes: 2 additions & 1 deletion src/Arguments.h
Original file line number Diff line number Diff line change
Expand Up @@ -63,7 +63,8 @@ class Arguments : public HelpArguments
None,
Export,
//Import,
Patch
Patch,
Tools
};
Arguments();
inline Command command() const {
Expand Down
58 changes: 58 additions & 0 deletions src/ArgumentsTools.cpp
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
/****************************************************************************
** Copyright (C) 2009-2021 Arzel Jérôme <[email protected]>
**
** 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "ArgumentsTools.h"

ArgumentsTools::ArgumentsTools() : CommonArguments()
{
_parser.addPositionalArgument("directory", QCoreApplication::translate("ArgumentsTools", "Input/Output directory."));

parse();
}

QDir ArgumentsTools::dir() const
{
return QDir(_directory);
}

void ArgumentsTools::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) {
// Input/Output directory
if (QDir(paths.last()).exists()) {
_directory = paths.takeLast();
} else {
qWarning() << qPrintable(
QCoreApplication::translate("Arguments", "Error: directory does not exist:"))
<< qPrintable(paths.last());
exit(1);
}

if (!paths.isEmpty()) {
_path = paths.first();
}
}
mapNamesFromFiles();
}
30 changes: 30 additions & 0 deletions src/ArgumentsTools.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
/****************************************************************************
** Copyright (C) 2009-2021 Arzel Jérôme <[email protected]>
**
** 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#pragma once

#include <QtCore>
#include "Arguments.h"

class ArgumentsTools : public CommonArguments
{
public:
ArgumentsTools();
QDir dir() const;
private:
void parse();
QString _directory;
};
72 changes: 72 additions & 0 deletions src/CLI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@
#include "Arguments.h"
#include "ArgumentsExport.h"
#include "ArgumentsPatch.h"
#include "ArgumentsTools.h"
#include "core/field/FieldArchivePS.h"
#include "core/field/FieldArchivePC.h"
#include "core/field/BackgroundFilePC.h"
Expand Down Expand Up @@ -251,6 +252,74 @@ void CLI::commandPatch()
delete fieldArchive;
}

void CLI::commandTools()
{
ArgumentsTools argsTools;
if (argsTools.help() || argsTools.path().isEmpty()) {
argsTools.showHelp();
}

FieldArchive *fieldArchive = openFieldArchive(argsTools.inputFormat(), argsTools.path());
if (fieldArchive == nullptr) {
return;
}

QList<int> selectedFields;
QList<QRegularExpression> includes, excludes;
QStringList includePatterns = argsTools.includes(), excludePatterns = argsTools.excludes();

for (const QString &pattern: includePatterns) {
includes.append(QRegularExpression(QRegularExpression::anchoredPattern(QRegularExpression::wildcardToRegularExpression(pattern))));
}
for (const QString &pattern: excludePatterns) {
excludes.append(QRegularExpression(QRegularExpression::anchoredPattern(QRegularExpression::wildcardToRegularExpression(pattern))));
}

FieldArchiveIterator it(*fieldArchive);
while (it.hasNext()) {
const Field *field = it.next(false);
if (field != nullptr) {
bool found = includes.isEmpty();
for (const QRegularExpression &regExp: includes) {
if (regExp.match(field->name()).hasMatch()) {
found = true;
break;
}
}
for (const QRegularExpression &regExp: excludes) {
if (regExp.match(field->name()).hasMatch()) {
found = false;
break;
}
}

if (found) {
selectedFields.append(it.mapId());
}
}
}

observer.setObserverMaximum(uint(selectedFields.size()));

int i = 0;

for (const int &mapID : selectedFields) {
Field *field = fieldArchive->field(mapID);
if (field != nullptr) {
if (fieldArchive->isPC()) {
BackgroundFilePC *bg = static_cast<BackgroundFilePC *>(field->background());
if (bg->isOpen()) {
bg->untile(argsTools.dir());
}
}
}

observer.setObserverValue(i++);
}

delete fieldArchive;
}

FieldArchive *CLI::openFieldArchive(const QString &ext, const QString &path)
{
bool isPS;
Expand Down Expand Up @@ -343,5 +412,8 @@ void CLI::exec()
case Arguments::Patch:
commandPatch();
break;
case Arguments::Tools:
commandTools();
break;
}
}
1 change: 1 addition & 0 deletions src/CLI.h
Original file line number Diff line number Diff line change
Expand Up @@ -50,6 +50,7 @@ class CLI
private:
static void commandExport();
static void commandPatch();
static void commandTools();
static FieldArchive *openFieldArchive(const QString &ext, const QString &path);
static CLIObserver observer;
};
81 changes: 81 additions & 0 deletions src/core/field/BackgroundFilePC.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -494,3 +494,84 @@ bool BackgroundFilePC::addPalette(const char *data)

return false;
}

bool BackgroundFilePC::untile(const QDir &dir) const
{
BackgroundTexturesPC *texs = textures();
QMap<uint8_t, QImage> images;

for (uint8_t i = 0; i < BACKGROUND_TEXTURE_PC_MAX_COUNT; ++i) {
if (texs->hasTex(i)) {
QString fileName = QString("%1_%2_00").arg(field()->name()).arg(i, 2, 10, QChar('0'));
QImage image;
if (!image.load(dir.filePath(QString("%1.png").arg(fileName)))) {
qWarning() << "Texture not found (only PNG format is supported)" << dir.filePath(fileName);
return false;
}
images.insert(i, image);
}
}

return untile(images);
}

bool BackgroundFilePC::untile(const QMap<uint8_t, QImage> &images) const
{
QSet<quint64> collect;
QMultiMap<quint64, Tile> tilesPerTargetImage;
int scale = images.first().width() / 256;
QRect area = tiles().rect();

for (int layerId = 0; layerId < 4; ++layerId) {
BackgroundTiles ts = tiles().tiles(layerId, true);
const int layer = layerId == 0 ? 0 : layerId - 1;
for (const Tile &tile: ts) {
// Use the same naming than Palmer
quint32 i = layerId == 1 ? 128 : 0;

if (tile.param > 0) {
i += 256 + (tile.param + tile.state * 64) * 4;
}

if (tile.blending) {
i += 64 * 256 * 4;
}

quint64 x = 64 + ((tile.dstX + std::abs(tile.dstX % 16)) / 16),
y = 64 + ((tile.dstY + std::abs(tile.dstY % 16)) / 16);

quint64 key = quint64(i) | ((x * 128 + y) << 32);

while (collect.contains(key)) {
i += 1;
key = quint64(i) | ((x * 128 + y) << 32);
}

collect.insert(key);

tilesPerTargetImage.insert(quint64(i) | (quint64(layer) << 32), tile);
}
}

QList<quint64> keys = tilesPerTargetImage.uniqueKeys();

for (quint64 key: keys) {
QList<Tile> tiles = tilesPerTargetImage.values(key);
quint64 layer = key >> 32;
quint64 i = key & 0xFFFFFFFF;
QImage image(area.size() * scale, QImage::Format_ARGB32_Premultiplied);
QPainter p(&image);

for (const Tile &tile: tiles) {
p.drawImage((area.topLeft() + QPoint(tile.dstX, tile.dstY)) * scale,
images.value(tile.textureID),
QRect(QPoint(tile.srcX, tile.srcY) * scale, QSize(tile.size, tile.size) * scale));
}

p.end();
QString fileName = QString("%1_%2_%3.png").arg(field()->name()).arg(layer).arg(i, 8, 10, QChar('0'));
image.save(fileName);
}

return true;
}
2 changes: 2 additions & 0 deletions src/core/field/BackgroundFilePC.h
Original file line number Diff line number Diff line change
Expand Up @@ -48,6 +48,8 @@ class BackgroundFilePC : public BackgroundFile
const QString &lastErrorString() const {
return _lastError;
}
bool untile(const QDir &dir) const;
bool untile(const QMap<uint8_t, QImage> &images) const;
private:
using BackgroundFile::open;
QString _lastError;
Expand Down

0 comments on commit b65605e

Please sign in to comment.