support external patches

main
Síle Ekaterin Liszka 2023-07-02 00:08:51 -07:00
parent 3507652ba9
commit b2f8512a2a
98 changed files with 136 additions and 87 deletions

View File

Before

Width:  |  Height:  |  Size: 9.3 KiB

After

Width:  |  Height:  |  Size: 9.3 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 5.8 KiB

After

Width:  |  Height:  |  Size: 5.8 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Before

Width:  |  Height:  |  Size: 3.9 KiB

After

Width:  |  Height:  |  Size: 3.9 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 6.8 KiB

After

Width:  |  Height:  |  Size: 6.8 KiB

View File

Before

Width:  |  Height:  |  Size: 5.3 KiB

After

Width:  |  Height:  |  Size: 5.3 KiB

View File

Before

Width:  |  Height:  |  Size: 2.4 KiB

After

Width:  |  Height:  |  Size: 2.4 KiB

View File

Before

Width:  |  Height:  |  Size: 3.0 KiB

After

Width:  |  Height:  |  Size: 3.0 KiB

View File

Before

Width:  |  Height:  |  Size: 3.7 KiB

After

Width:  |  Height:  |  Size: 3.7 KiB

View File

Before

Width:  |  Height:  |  Size: 9.8 KiB

After

Width:  |  Height:  |  Size: 9.8 KiB

View File

Before

Width:  |  Height:  |  Size: 2.6 KiB

After

Width:  |  Height:  |  Size: 2.6 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 1.5 KiB

After

Width:  |  Height:  |  Size: 1.5 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.4 KiB

After

Width:  |  Height:  |  Size: 5.4 KiB

View File

Before

Width:  |  Height:  |  Size: 5.0 KiB

After

Width:  |  Height:  |  Size: 5.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 6.2 KiB

After

Width:  |  Height:  |  Size: 6.2 KiB

View File

Before

Width:  |  Height:  |  Size: 5.6 KiB

After

Width:  |  Height:  |  Size: 5.6 KiB

View File

Before

Width:  |  Height:  |  Size: 4.1 KiB

After

Width:  |  Height:  |  Size: 4.1 KiB

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 4.7 KiB

After

Width:  |  Height:  |  Size: 4.7 KiB

View File

Before

Width:  |  Height:  |  Size: 8.8 KiB

After

Width:  |  Height:  |  Size: 8.8 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 5.2 KiB

After

Width:  |  Height:  |  Size: 5.2 KiB

View File

Before

Width:  |  Height:  |  Size: 4.5 KiB

After

Width:  |  Height:  |  Size: 4.5 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 11 KiB

After

Width:  |  Height:  |  Size: 11 KiB

View File

Before

Width:  |  Height:  |  Size: 2.2 KiB

After

Width:  |  Height:  |  Size: 2.2 KiB

View File

Before

Width:  |  Height:  |  Size: 7.0 KiB

After

Width:  |  Height:  |  Size: 7.0 KiB

View File

Before

Width:  |  Height:  |  Size: 5.7 KiB

After

Width:  |  Height:  |  Size: 5.7 KiB

View File

Before

Width:  |  Height:  |  Size: 7.8 KiB

After

Width:  |  Height:  |  Size: 7.8 KiB

View File

Before

Width:  |  Height:  |  Size: 69 KiB

After

Width:  |  Height:  |  Size: 69 KiB

View File

Before

Width:  |  Height:  |  Size: 10 KiB

After

Width:  |  Height:  |  Size: 10 KiB

View File

Before

Width:  |  Height:  |  Size: 5.1 KiB

After

Width:  |  Height:  |  Size: 5.1 KiB

View File

Before

Width:  |  Height:  |  Size: 6.7 KiB

After

Width:  |  Height:  |  Size: 6.7 KiB

View File

Before

Width:  |  Height:  |  Size: 4.9 KiB

After

Width:  |  Height:  |  Size: 4.9 KiB

View File

Before

Width:  |  Height:  |  Size: 3.3 KiB

After

Width:  |  Height:  |  Size: 3.3 KiB

View File

Before

Width:  |  Height:  |  Size: 4.4 KiB

After

Width:  |  Height:  |  Size: 4.4 KiB

View File

Before

Width:  |  Height:  |  Size: 2.0 KiB

After

Width:  |  Height:  |  Size: 2.0 KiB

View File

Before

Width:  |  Height:  |  Size: 24 KiB

After

Width:  |  Height:  |  Size: 24 KiB

View File

Before

Width:  |  Height:  |  Size: 9.5 KiB

After

Width:  |  Height:  |  Size: 9.5 KiB

View File

View File

@ -1,6 +1,6 @@
HEADERS += src/exdeath.hh src/data.hh src/randodata.hh src/randomizer.hh src/fiesta.hh
SOURCES += src/exdeath.cc src/main.cc src/randomizer.cc src/fiesta.cc
HEADERS += src/exdeath.hh src/data.hh src/randodata.hh src/randomizer.hh src/fiesta.hh src/patch.hh
SOURCES += src/exdeath.cc src/main.cc src/randomizer.cc src/fiesta.cc src/patch.cc
RESOURCES += patches.qrc
CONFIG += release

View File

@ -30,6 +30,7 @@
#include <iostream>
#include "exdeath.hh"
#include "patch.hh"
#include <cstring>
#include <cstdlib>
@ -37,7 +38,7 @@
#include <ctime>
#include <climits>
Exdeath::Exdeath(QSettings *cfg, QWidget *parent) : QWidget(parent) {
Exdeath::Exdeath(QSettings *cfg, QList<QPair<QString,QString> > modes, QList<QPair<QString,QString> > NEDs, QWidget *parent) : QWidget(parent) {
error = new QErrorMessage();
filename = nullptr;
_cfg = cfg;
@ -52,15 +53,15 @@ Exdeath::Exdeath(QSettings *cfg, QWidget *parent) : QWidget(parent) {
layColumns->addLayout(layLeft);
layColumns->addLayout(layRight);
initMain();
initRandom();
initMain(modes);
initRandom(NEDs);
initInnates();
initMulti();
initPreview();
initConfig();
connect(btnROM, &QPushButton::clicked, this, &Exdeath::btnROM_clicked);
connect(selMode, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &Exdeath::selMode_index);
connect(selMode, QOverload<int>::of(&QComboBox::activated), this, &Exdeath::selMode_index);
connect(selNED, QOverload<int>::of(&QComboBox::currentIndexChanged), this, &Exdeath::selNED_index);
connect(btnApply, &QPushButton::clicked, this, &Exdeath::btnApply_clicked);
connect(btnSave, &QPushButton::clicked, this, &Exdeath::btnSave_clicked);
@ -68,7 +69,7 @@ Exdeath::Exdeath(QSettings *cfg, QWidget *parent) : QWidget(parent) {
Exdeath::~Exdeath() {}
void Exdeath::initMain(void) {
void Exdeath::initMain(QList<QPair<QString,QString> > modes) {
layMain = new QGridLayout(this);
grpMain = new QGroupBox("Main");
grpMain->setLayout(layMain);
@ -80,10 +81,12 @@ void Exdeath::initMain(void) {
txtMode = new QLabel("Mode:");
selMode = new QComboBox();
selMode->addItem("Base");
selMode->addItem("Ian's Balance", "Ian's Balance Patch.ips");
selMode->addItem("Waddler Rebalance", "waddle.ips");
selMode->addItem("Balance", "balance.ips");
selMode->addItem("Custom Classes", "custom_classes.ips");
for (int i = 0; i < modes.size(); i++) {
QPair<QString,QString> file = modes.at(i);
selMode->addItem(file.first, file.second);
}
txtUnlock = new QLabel("Unlock Jobs:");
chkUnlock = new QCheckBox("Yes");
@ -112,7 +115,7 @@ void Exdeath::initMain(void) {
layMain->addWidget(btnSave, 5, 1);
}
void Exdeath::initRandom(void) {
void Exdeath::initRandom(QList<QPair<QString,QString> > NEDs) {
layRandom = new QFormLayout(this);
grpRandom = new QGroupBox("Randomization");
grpRandom->setLayout(layRandom);
@ -128,47 +131,11 @@ void Exdeath::initRandom(void) {
selNED->addItem("Random", "random");
selNED->addItem("Vanilla", "vanilla");
selNED->setCurrentIndex(1);
selNED->addItem("Absolute Virtue", "abs_vir");
selNED->addItem("Barf", "barf");
selNED->addItem("Biolizard", "biolizard");
selNED->addItem("Cactuar", "cactuar");
selNED->addItem("Chain Chomp", "chomp");
//selNED->addItem("Classic", "classic");
selNED->addItem("Chaos", "chaos");
selNED->addItem("Cloud of Darkness", "cad");
selNED->addItem("Doomtrain", "train");
selNED->addItem("Emperor", "emperor");
selNED->addItem("Fat Chocobo", "NeoExChonk");
selNED->addItem("Fiends", "fiend_ned");
selNED->addItem("Flammie (1)", "flammie1");
selNED->addItem("Flammie (2)", "flammie2");
selNED->addItem("Fly", "fly");
selNED->addItem("Godzilla", "godzilla");
selNED->addItem("Guy Fieri", "flavortown");
selNED->addItem("Jace", "Jace");
selNED->addItem("Lavos Spawn", "lavos-spawn");
selNED->addItem("Kefka", "kefka");
selNED->addItem("Majima", "Majima");
selNED->addItem("Majima (flipped)", "MajimaFlipped");
selNED->addItem("MechaGodzilla", "mechagodzilla");
selNED->addItem("Metroid", "metroid");
selNED->addItem("Neo X Death", "neo-x-death");
selNED->addItem("Neo ExDesert", "NeoExDesert");
selNED->addItem("Neo ExDuck", "neoexduck");
selNED->addItem("Neon ExDeath", "fancy");
selNED->addItem("Nero Exdeath", "nero_exdeath");
selNED->addItem("Omega Larboard Cannon", "omega_cannon");
selNED->addItem("Puzzle & Dragon", "pad");
selNED->addItem("Romancing SaGa 3 Boss", "rs3boss");
selNED->addItem("Shaq", "shaq");
selNED->addItem("Stupid Sexy Flanders", "flanders");
selNED->addItem("TargetNED", "targetned");
selNED->addItem("Territorial Oak", "tree");
selNED->addItem("Thomas the Tank Engine", "thomas");
selNED->addItem("Warriors of Light", "BizarroParty");
selNED->addItem("Warriors of Light (Fiesta)", "FiestaParty");
selNED->addItem("Yiazmat", "yiazmat");
selNED->addItem("Zeromus", "Zeromus");
for (int i = 0; i < NEDs.size(); i++) {
QPair<QString,QString> file = NEDs.at(i);
selNED->addItem(file.first, file.second);
}
layRandom->addRow("Neo ExDeath:", selNED);
chkRandom = new QCheckBox("Yes");
@ -312,40 +279,26 @@ void Exdeath::initConfig(void) {
}
void Exdeath::selNED_index(int idx) {
imgPreview = new QPixmap(":/gallery/ned/" + selNED->itemData(idx).toString() + ".png");
QString filename = selNED->itemData(idx).toString();
if (!filename.startsWith(":")) {
filename.append(".png");
}
imgPreview = new QPixmap(filename);
txtPreview->setPixmap(*imgPreview);
}
void Exdeath::selMode_index(int idx) {
bool random_ok = false;
bool unlock_ok = false;
bool innate_ok = false;
bool sound_ok = false;
bool ned_ok = false;
if (idx == 0) return;
int ret = QMessageBox::warning(
this,
tr("Exdeath"),
tr("Using a mode other than Base may cause innate abilities, ability randomization, or Neo Exdeath graphic changes to break the game.\nAre you sure you want to do this?"),
QMessageBox::Yes | QMessageBox::No
);
if (idx < 3) {
unlock_ok = true;
innate_ok = true;
sound_ok = true;
ned_ok = true;
if (ret == QMessageBox::No) {
selMode->setCurrentIndex(0);
}
if (idx <= 1) {
random_ok = true;
}
chkRandom->setEnabled(random_ok);
chkUnlock->setEnabled(unlock_ok);
chkSound->setEnabled(sound_ok);
selNED->setEnabled(ned_ok);
chkPassages->setEnabled(innate_ok);
chkPitfalls->setEnabled(innate_ok);
chkLiteStep->setEnabled(innate_ok);
chkDash->setEnabled(innate_ok);
chkLearning->setEnabled(innate_ok);
innates_enabled = innate_ok;
}
void Exdeath::btnSave_clicked(bool trigger) {
@ -411,7 +364,11 @@ void Exdeath::btnApply_clicked(bool trigger) {
QString output = QFileDialog::getSaveFileName(
this,
"Select target ROM image",
#ifdef __WIN32__
QApplication::applicationDirPath(),
#else
QStandardPaths::standardLocations(QStandardPaths::DocumentsLocation)[0],
#endif
"GBA ROM images (*.gba)"
);
QFile::copy(filename, output);
@ -423,7 +380,7 @@ void Exdeath::btnApply_clicked(bool trigger) {
patches << ":/patches/fixnames.ips";
if (mode > 0) {
patches << ":/patches/" + selMode->itemData(mode).toString();
patches << selMode->itemData(mode).toString();
}
if (chkUnlock->isChecked() && chkUnlock->isEnabled()) {
patches << ":/patches/unlock.ips";

View File

@ -15,6 +15,7 @@
#include <QGroupBox>
#include <QIODevice>
#include <QLabel>
#include <QList>
#include <QPixmap>
#include <QPushButton>
#include <QRadioButton>
@ -32,7 +33,7 @@
class Exdeath : public QWidget {
public:
Exdeath(QSettings *cfg, QWidget *parent = nullptr);
Exdeath(QSettings *cfg, QList<QPair<QString,QString> > modes, QList<QPair<QString,QString> > NEDs, QWidget *parent = nullptr);
~Exdeath();
private:
@ -105,9 +106,9 @@ private:
QPixmap *imgPreview;
// Initialization
void initMain(void);
void initMain(QList<QPair<QString,QString> > modes);
void initInnates(void);
void initRandom(void);
void initRandom(QList<QPair<QString,QString> > NEDs);
void initMulti(void);
void initPreview(void);
void initConfig(void);

View File

@ -26,8 +26,10 @@
*/
#include "exdeath.hh"
#include "patch.hh"
#include <QApplication>
#include <iostream>
int main(int argc, char **argv) {
QApplication *app = new QApplication(argc, argv);
@ -35,10 +37,20 @@ int main(int argc, char **argv) {
QApplication::setOrganizationDomain("aerdan.org");
QApplication::setApplicationName("Exdeath");
QApplication::setApplicationDisplayName("Exdeath");
QApplication::setApplicationVersion("0.9.2");
QApplication::setApplicationVersion("0.10.0");
#ifdef __WIN32__
QString path = QApplication::applicationDirPath();
#else
QString path = QStandardPaths::standardLocations(QStandardPaths::AppDataLocation)[0];
#endif
QDir dir = QDir(path);
std::cout << "Searching in" << path.toStdString() << std::endl;
QList<QPair<QString,QString> > modes = getPatchList(dir, PatchType::Mode);
QList<QPair<QString,QString> > NEDs = getPatchList(dir, PatchType::NED);
QSettings *cfg = new QSettings();
Exdeath *win = new Exdeath(cfg);
Exdeath *win = new Exdeath(cfg, modes, NEDs);
win->show();

64
src/patch.cc Normal file
View File

@ -0,0 +1,64 @@
/*
* Copyright (c) 2023, Síle Ekaterin Liszka.
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
* * Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* * Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* * Neither the name of the software nor the
* names of its contributors may be used to endorse or promote products
* derived from this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
* WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
* DISCLAIMED. IN NO EVENT SHALL <COPYRIGHT HOLDER> BE LIABLE FOR ANY
* DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
* ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
* (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS
* SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
*/
#include "patch.hh"
QList<QPair<QString,QString> > getPatchList(QDir dir, PatchType type) {
QList<QPair<QString,QString> > list;
if (!dir.exists()) {
return list;
}
if (type == PatchType::Mode) {
dir.cd("modes");
if (!dir.exists()) {
return list;
}
} else if (type == PatchType::NED) {
dir.cd("ned");
if (!dir.exists()) {
return list;
}
}
dir.setFilter(QDir::Files | QDir::Readable);
dir.setSorting(QDir::Name);
QFileInfoList files = dir.entryInfoList();
for (int i = 0; i < files.size(); i++) {
QFileInfo file = files.at(i);
if (file.suffix() == "ips") {
QString filename = file.canonicalPath() + "/" + file.completeBaseName() + ".ips";
QPair<QString,QString> pair = {file.completeBaseName(), filename};
list.append(pair);
}
}
return list;
}

15
src/patch.hh Normal file
View File

@ -0,0 +1,15 @@
#pragma once
#include <QDir>
#include <QFileInfo>
#include <QList>
#include <QString>
enum PatchType {
Mode,
NED,
};
QList<QPair<QString,QString> > getPatchList(QDir dir, PatchType type);