Preliminary support for Project Demi-inspired innate ability mods
parent
2116465775
commit
557a8a5d83
|
@ -12,7 +12,9 @@ body {
|
||||||
<head>
|
<head>
|
||||||
<body>
|
<body>
|
||||||
<h2>Exdeath</h2>
|
<h2>Exdeath</h2>
|
||||||
<p>Exdeath is a patch compactor, a tool that applies multiple patches to a single target file. This version (0.2) provides the following options:</p>
|
<p>Exdeath is a patch compactor, a tool that applies multiple patches to a single target file. You will need the US version of the Gameboy Advance release, which you can find through your favourite search engine. This version provides the following features:</p>
|
||||||
|
<h3>Main</h3>
|
||||||
|
<p>The real meat of the program: the patches.</p>
|
||||||
<ul>
|
<ul>
|
||||||
<li>Base:<ul>
|
<li>Base:<ul>
|
||||||
<li>None — The base game.</li>
|
<li>None — The base game.</li>
|
||||||
|
@ -24,7 +26,8 @@ body {
|
||||||
<li><a href="https://drive.google.com/file/d/1kQeTEu55-Pt_0-fLSYIeUW50LxW6CcLN/view?usp=sharing">Double AP</a>: This option doubles the ABP gains, making it faster to master Jobs (most relevant for !Dualcast).</li>
|
<li><a href="https://drive.google.com/file/d/1kQeTEu55-Pt_0-fLSYIeUW50LxW6CcLN/view?usp=sharing">Double AP</a>: This option doubles the ABP gains, making it faster to master Jobs (most relevant for !Dualcast).</li>
|
||||||
<li><a href="http://www.romhacking.net/hacks/563/">Sound Restoration</a>: This option modifies the soundfont and corrects some slow-down issues. It can cause artifacting, however. Older versions of VisualBoyAdvance will require the GBA BIOS file in order to run normally with this option.</li>
|
<li><a href="http://www.romhacking.net/hacks/563/">Sound Restoration</a>: This option modifies the soundfont and corrects some slow-down issues. It can cause artifacting, however. Older versions of VisualBoyAdvance will require the GBA BIOS file in order to run normally with this option.</li>
|
||||||
</ul>
|
</ul>
|
||||||
<p>You will need the US version of the Gameboy Advance release, which you can find through your favourite search engine.</p>
|
<h3>Innate abilities</h3>
|
||||||
|
<p>Each checkbox applies the listed innate ability to all Jobs.</p>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,9 @@
|
||||||
|
enum Job {
|
||||||
|
Passages = 0x01,
|
||||||
|
Pitfalls = 0x02,
|
||||||
|
LiteStep = 0x04,
|
||||||
|
Dash = 0x08,
|
||||||
|
Learning = 0x10
|
||||||
|
};
|
||||||
|
|
||||||
|
const long int job_innates = 0x156138;
|
|
@ -34,9 +34,20 @@ Exdeath::Exdeath(QWidget *parent) : QWidget(parent) {
|
||||||
error = new QErrorMessage();
|
error = new QErrorMessage();
|
||||||
filename = nullptr;
|
filename = nullptr;
|
||||||
|
|
||||||
|
layContainer = new QVBoxLayout(this);
|
||||||
|
|
||||||
layMain = new QGridLayout(this);
|
layMain = new QGridLayout(this);
|
||||||
layMode = new QVBoxLayout(this);
|
layMode = new QVBoxLayout(this);
|
||||||
|
layDemi = new QVBoxLayout(this);
|
||||||
|
|
||||||
|
grpMain = new QGroupBox("Main");
|
||||||
|
grpMain->setLayout(layMain);
|
||||||
|
grpDemi = new QGroupBox("Innate abilities");
|
||||||
|
grpDemi->setLayout(layDemi);
|
||||||
|
layContainer->addWidget(grpMain);
|
||||||
|
layContainer->addWidget(grpDemi);
|
||||||
|
|
||||||
|
// Main options
|
||||||
txtROM = new QLabel("ROM:");
|
txtROM = new QLabel("ROM:");
|
||||||
txtMode = new QLabel("Mode:");
|
txtMode = new QLabel("Mode:");
|
||||||
txtPortraits = new QLabel("FFT-style Portraits:");
|
txtPortraits = new QLabel("FFT-style Portraits:");
|
||||||
|
@ -46,6 +57,7 @@ Exdeath::Exdeath(QWidget *parent) : QWidget(parent) {
|
||||||
|
|
||||||
btnROM = new QPushButton("Select ROM");
|
btnROM = new QPushButton("Select ROM");
|
||||||
btnApply = new QPushButton("Apply");
|
btnApply = new QPushButton("Apply");
|
||||||
|
layContainer->addWidget(btnApply);
|
||||||
|
|
||||||
radBase = new QRadioButton("Base");
|
radBase = new QRadioButton("Base");
|
||||||
radFiesta = new QRadioButton("Fiesta");
|
radFiesta = new QRadioButton("Fiesta");
|
||||||
|
@ -71,8 +83,18 @@ Exdeath::Exdeath(QWidget *parent) : QWidget(parent) {
|
||||||
layMain->addWidget(chkAP, 3, 1);
|
layMain->addWidget(chkAP, 3, 1);
|
||||||
layMain->addWidget(txtSound, 4, 0);
|
layMain->addWidget(txtSound, 4, 0);
|
||||||
layMain->addWidget(chkSound, 4, 1);
|
layMain->addWidget(chkSound, 4, 1);
|
||||||
layMain->addWidget(btnApply, 5, 1);
|
|
||||||
|
|
||||||
|
// Project Demi options
|
||||||
|
chkPassages = new QCheckBox("Innate Passages");
|
||||||
|
chkPitfalls = new QCheckBox("Innate Pitfalls");
|
||||||
|
chkLiteStep = new QCheckBox("Innate Light Step");
|
||||||
|
chkDash = new QCheckBox("Innate Dash");
|
||||||
|
chkLearning = new QCheckBox("Innate Learning");
|
||||||
|
layDemi->addWidget(chkPassages);
|
||||||
|
layDemi->addWidget(chkPitfalls);
|
||||||
|
layDemi->addWidget(chkLiteStep);
|
||||||
|
layDemi->addWidget(chkDash);
|
||||||
|
layDemi->addWidget(chkLearning);
|
||||||
connect(btnROM, &QPushButton::clicked, this, &Exdeath::btnROM_clicked);
|
connect(btnROM, &QPushButton::clicked, this, &Exdeath::btnROM_clicked);
|
||||||
connect(btnApply, &QPushButton::clicked, this, &Exdeath::btnApply_clicked);
|
connect(btnApply, &QPushButton::clicked, this, &Exdeath::btnApply_clicked);
|
||||||
}
|
}
|
||||||
|
@ -129,17 +151,16 @@ void Exdeath::btnApply_clicked(bool trigger) {
|
||||||
patches << ":/patches/sound_restoration.ips";
|
patches << ":/patches/sound_restoration.ips";
|
||||||
}
|
}
|
||||||
|
|
||||||
if (patches.size() == 0) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
target = new QFile(output);
|
target = new QFile(output);
|
||||||
target->open(QIODevice::ReadWrite);
|
target->open(QIODevice::ReadWrite);
|
||||||
|
if (patches.size() != 0) {
|
||||||
for (int i = 0; i < patches.size(); i++) {
|
for (int i = 0; i < patches.size(); i++) {
|
||||||
applyPatch(target, patches[i]);
|
applyPatch(target, patches[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (chkPassages->isChecked() || chkPitfalls->isChecked() || chkLiteStep->isChecked() || chkDash->isChecked() || chkLearning->isChecked()) {
|
||||||
|
applyDemi(target);
|
||||||
}
|
}
|
||||||
|
|
||||||
target->close();
|
target->close();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -183,3 +204,26 @@ void Exdeath::applyPatch(QFile *file, QString patch) {
|
||||||
file->flush();
|
file->flush();
|
||||||
data->close();
|
data->close();
|
||||||
}
|
}
|
||||||
|
void Exdeath::applyDemi(QFile *file) {
|
||||||
|
unsigned char base = 0;
|
||||||
|
|
||||||
|
if (!(radBase->isChecked() || radFiesta->isChecked())) {
|
||||||
|
error->showMessage("You must use Base or Fiesta to use these options.");
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (chkPassages->isChecked()) base |= Job::Passages;
|
||||||
|
if (chkPitfalls->isChecked()) base |= Job::Pitfalls;
|
||||||
|
if (chkLiteStep->isChecked()) base |= Job::LiteStep;
|
||||||
|
if (chkDash->isChecked()) base |= Job::Dash;
|
||||||
|
if (chkLearning->isChecked()) base |= Job::Learning;
|
||||||
|
|
||||||
|
for (int i = 0; i < 26; i++) {
|
||||||
|
char temp[2];
|
||||||
|
file->seek(job_innates + (i * 2));
|
||||||
|
file->read(temp, 2);
|
||||||
|
temp[0] |= base;
|
||||||
|
file->seek(job_innates + (i * 2));
|
||||||
|
file->write(temp, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -1,19 +1,22 @@
|
||||||
#ifndef EXDEATH_HH_GUARD
|
#ifndef EXDEATH_HH_GUARD
|
||||||
#define EXDEATH_HH_GUARD
|
#define EXDEATH_HH_GUARD
|
||||||
|
|
||||||
#include <QWidget>
|
#include <QCheckBox>
|
||||||
|
#include <QCryptographicHash>
|
||||||
|
#include <QErrorMessage>
|
||||||
|
#include <QFile>
|
||||||
|
#include <QFileDialog>
|
||||||
#include <QGridLayout>
|
#include <QGridLayout>
|
||||||
#include <QVBoxLayout>
|
#include <QGroupBox>
|
||||||
|
#include <QIODevice>
|
||||||
#include <QLabel>
|
#include <QLabel>
|
||||||
#include <QPushButton>
|
#include <QPushButton>
|
||||||
#include <QRadioButton>
|
#include <QRadioButton>
|
||||||
#include <QCheckBox>
|
|
||||||
#include <QFileDialog>
|
|
||||||
#include <QStandardPaths>
|
#include <QStandardPaths>
|
||||||
#include <QFile>
|
#include <QVBoxLayout>
|
||||||
#include <QIODevice>
|
#include <QWidget>
|
||||||
#include <QCryptographicHash>
|
|
||||||
#include <QErrorMessage>
|
#include "data.hh"
|
||||||
|
|
||||||
class Exdeath : public QWidget {
|
class Exdeath : public QWidget {
|
||||||
public:
|
public:
|
||||||
|
@ -25,8 +28,10 @@ private:
|
||||||
|
|
||||||
QErrorMessage *error;
|
QErrorMessage *error;
|
||||||
|
|
||||||
|
QVBoxLayout *layContainer;
|
||||||
QGridLayout *layMain;
|
QGridLayout *layMain;
|
||||||
QVBoxLayout *layMode;
|
QVBoxLayout *layMode;
|
||||||
|
QGroupBox *grpMain;
|
||||||
|
|
||||||
QLabel *txtROM;
|
QLabel *txtROM;
|
||||||
QLabel *txtMode;
|
QLabel *txtMode;
|
||||||
|
@ -46,9 +51,19 @@ private:
|
||||||
QCheckBox *chkAP;
|
QCheckBox *chkAP;
|
||||||
QCheckBox *chkSound;
|
QCheckBox *chkSound;
|
||||||
|
|
||||||
|
QGroupBox *grpDemi;
|
||||||
|
QVBoxLayout *layDemi;
|
||||||
|
|
||||||
|
QCheckBox *chkPassages;
|
||||||
|
QCheckBox *chkPitfalls;
|
||||||
|
QCheckBox *chkLiteStep;
|
||||||
|
QCheckBox *chkDash;
|
||||||
|
QCheckBox *chkLearning;
|
||||||
|
|
||||||
void btnROM_clicked(bool trigger);
|
void btnROM_clicked(bool trigger);
|
||||||
void btnApply_clicked(bool trigger);
|
void btnApply_clicked(bool trigger);
|
||||||
void applyPatch(QFile *file, QString patch);
|
void applyPatch(QFile *file, QString patch);
|
||||||
|
void applyDemi(QFile *file);
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif
|
#endif
|
Loading…
Reference in New Issue