mirror of
https://github.com/huderlem/porymap.git
synced 2026-08-15 21:32:12 -05:00
Allow INCBIN regex to change, support INCGFX by default
This commit is contained in:
@@ -5,6 +5,9 @@ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
|
||||
and this project somewhat adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). The MAJOR version number is bumped when there are **"Breaking Changes"** in the pret projects. For more on this, see [the manual page on breaking changes](https://huderlem.github.io/porymap/manual/breaking-changes.html).
|
||||
|
||||
## [Unreleased]
|
||||
### Added
|
||||
- Support `INCGFX` in addition to `INCBIN`. The regular expression for these statements is now available under `Project Settings`.
|
||||
|
||||
### Fixed
|
||||
- Fix degraded image quality in exported timelapse gifs.
|
||||
- Fix custom top-level data in the `encounters` object of `wild_encounters.json` being discarded if no `fields` data is present.
|
||||
|
||||
@@ -244,6 +244,7 @@ enum ProjectIdentifier {
|
||||
regex_music,
|
||||
regex_encounter_types,
|
||||
regex_terrain_types,
|
||||
regex_incbin,
|
||||
pals_output_extension,
|
||||
tiles_output_extension,
|
||||
};
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "log.h"
|
||||
#include "orderedjson.h"
|
||||
#include "orderedmap.h"
|
||||
#include "regex.h"
|
||||
|
||||
#include <QString>
|
||||
#include <QList>
|
||||
@@ -73,6 +74,8 @@ public:
|
||||
bool tryParseJsonFile(QJsonDocument *out, const QString &filepath, QString *error = nullptr);
|
||||
bool tryParseOrderedJsonFile(poryjson::Json::object *out, const QString &filepath, QString *error = nullptr);
|
||||
|
||||
void setIncbinPattern(const QString& pattern);
|
||||
|
||||
static int getJsonLineNumber(const QString &filepath, const QString &searchText);
|
||||
|
||||
// Returns the 1-indexed line number for the definition of scriptLabel in the scripts file at filePath.
|
||||
@@ -102,6 +105,10 @@ private:
|
||||
QHash<QString, QString> fileCache;
|
||||
QHash<QString, QStringList> errorMap;
|
||||
|
||||
QString incbinPattern = Regex::Pattern_INCBIN;
|
||||
std::unique_ptr<QRegularExpression> incbinRegex = nullptr;
|
||||
std::unique_ptr<QRegularExpression> incbinArrayRegex = nullptr;
|
||||
|
||||
// The maps of define names to values/expressions that are available while parsing C defines.
|
||||
// As the parser reads and evaluates more defines it will update these maps accordingly.
|
||||
QHash<QString, int> knownDefineValues;
|
||||
@@ -140,7 +147,6 @@ private:
|
||||
static const QRegularExpression re_poryScriptLabel;
|
||||
static const QRegularExpression re_globalPoryScriptLabel;
|
||||
static const QRegularExpression re_poryRawSection;
|
||||
static const QString incbinRegexText;
|
||||
};
|
||||
|
||||
#endif // PARSEUTIL_H
|
||||
|
||||
9
include/core/regex.h
Normal file
9
include/core/regex.h
Normal file
@@ -0,0 +1,9 @@
|
||||
#pragma once
|
||||
#ifndef REGEX_H
|
||||
#define REGEX_H
|
||||
|
||||
namespace Regex {
|
||||
constexpr auto Pattern_INCBIN = R"(INC(BIN|GFX)_\w+?\s*\(\s*\"(?<path>[^\"]*)\"[^\)]*\))";
|
||||
};
|
||||
|
||||
#endif // REGEX_H
|
||||
@@ -5,6 +5,7 @@
|
||||
#include "validator.h"
|
||||
#include "utility.h"
|
||||
#include "metatile.h"
|
||||
#include "regex.h"
|
||||
#include <QDir>
|
||||
#include <QFile>
|
||||
#include <QFormLayout>
|
||||
@@ -133,6 +134,7 @@ const QMap<ProjectIdentifier, QPair<QString, QString>> ProjectConfig::defaultIde
|
||||
{ProjectIdentifier::regex_music, {"regex_music", "\\b(SE|MUS)_"}},
|
||||
{ProjectIdentifier::regex_encounter_types, {"regex_encounter_types", "\\bTILE_ENCOUNTER_"}},
|
||||
{ProjectIdentifier::regex_terrain_types, {"regex_terrain_types", "\\bTILE_TERRAIN_"}},
|
||||
{ProjectIdentifier::regex_incbin, {"regex_incbin", Regex::Pattern_INCBIN}},
|
||||
// Other
|
||||
{ProjectIdentifier::pals_output_extension, {"pals_output_extension", ".gbapal"}},
|
||||
{ProjectIdentifier::tiles_output_extension, {"tiles_output_extension", ".4bpp.lz"}},
|
||||
|
||||
@@ -16,7 +16,6 @@ const QRegularExpression ParseUtil::re_globalIncScriptLabel("\\b(?<label>[\\w_][
|
||||
const QRegularExpression ParseUtil::re_poryScriptLabel("\\b(script)(\\((global|local)\\))?\\s*\\b(?<label>[\\w_][\\w\\d_]*)");
|
||||
const QRegularExpression ParseUtil::re_globalPoryScriptLabel("\\b(script)(\\((global)\\))?\\s*\\b(?<label>[\\w_][\\w\\d_]*)");
|
||||
const QRegularExpression ParseUtil::re_poryRawSection("\\b(raw)\\s*`(?<raw_script>[^`]*)");
|
||||
const QString ParseUtil::incbinRegexText(R"(INCBIN_[US][0-9][0-9]?\s*\(\s*\"(?<path>[^\"]*)\"[^\)]*\))");
|
||||
|
||||
ParseUtil::ParseUtil() {
|
||||
resetCDefines();
|
||||
@@ -330,6 +329,15 @@ int ParseUtil::evaluatePostfix(const QList<Token> &postfix) {
|
||||
return stack.size() ? stack.pop().value.toInt(nullptr, 0) : 0;
|
||||
}
|
||||
|
||||
void ParseUtil::setIncbinPattern(const QString& pattern) {
|
||||
this->incbinPattern = pattern;
|
||||
|
||||
// We need to regenerate regular expressions that depend on this pattern.
|
||||
// We'll wait until the next time they're needed to do that.
|
||||
this->incbinRegex = nullptr;
|
||||
this->incbinArrayRegex = nullptr;
|
||||
}
|
||||
|
||||
QString ParseUtil::readCIncbin(const QString &filename, const QString &label) {
|
||||
return !label.isEmpty() ? readCIncbinMulti(filename).value(label) : QString();
|
||||
}
|
||||
@@ -340,9 +348,11 @@ QMap<QString, QString> ParseUtil::readCIncbinMulti(const QString &filename) {
|
||||
this->file = filename;
|
||||
this->text = loadTextFile(filename);
|
||||
|
||||
static const QRegularExpression regex(QString(R"((?<label>[\w]+)\s*(?:\[[^\]]*\])?\s*=\s*%1)").arg(this->incbinRegexText));
|
||||
if (!this->incbinArrayRegex) {
|
||||
this->incbinArrayRegex = std::make_unique<QRegularExpression>(QString(R"((?<label>[\w]+)\s*(?:\[[^\]]*\])?\s*=\s*%1)").arg(this->incbinPattern));
|
||||
}
|
||||
|
||||
QRegularExpressionMatchIterator iter = regex.globalMatch(this->text);
|
||||
QRegularExpressionMatchIterator iter = this->incbinArrayRegex->globalMatch(this->text);
|
||||
while (iter.hasNext()) {
|
||||
QRegularExpressionMatch match = iter.next();
|
||||
QString label = match.captured("label");
|
||||
@@ -382,8 +392,10 @@ QStringList ParseUtil::readCIncbinArray(const QString &filename, const QString &
|
||||
}
|
||||
|
||||
// Extract incbin paths from the array
|
||||
static const QRegularExpression re_incbin(this->incbinRegexText);
|
||||
QRegularExpressionMatchIterator iter = re_incbin.globalMatch(arrayText);
|
||||
if (!this->incbinRegex) {
|
||||
this->incbinRegex = std::make_unique<QRegularExpression>(this->incbinPattern);
|
||||
}
|
||||
QRegularExpressionMatchIterator iter = this->incbinRegex->globalMatch(arrayText);
|
||||
while (iter.hasNext()) {
|
||||
paths.append(iter.next().captured("path"));
|
||||
}
|
||||
|
||||
@@ -172,8 +172,7 @@ bool RegionMap::loadLayout(poryjson::Json layoutJson) {
|
||||
}
|
||||
case LayoutFormat::CArray:
|
||||
{
|
||||
ParseUtil parser;
|
||||
QString text = parser.readTextFile(fullPath(this->layout_path));
|
||||
QString text = ParseUtil::readTextFile(fullPath(this->layout_path));
|
||||
|
||||
static const QRegularExpression re("(?<qual_1>static)?\\s?(?<qual_2>const)?\\s?(?<type>[A-Za-z0-9_]+)?\\s+(?<label>[A-Za-z0-9_]+)"
|
||||
"(\\[(?<const_1>[A-Za-z0-9_]+)\\])(\\[(?<const_2>[A-Za-z0-9_]+)\\])(\\[(?<const_3>[A-Za-z0-9_]+)\\])\\s+=");
|
||||
|
||||
@@ -32,7 +32,9 @@ int Project::num_pals_total = 13;
|
||||
|
||||
Project::Project(QObject *parent) :
|
||||
QObject(parent)
|
||||
{ }
|
||||
{
|
||||
this->parser.setIncbinPattern(projectConfig.getIdentifier(ProjectIdentifier::regex_incbin));
|
||||
}
|
||||
|
||||
Project::~Project()
|
||||
{
|
||||
|
||||
@@ -337,17 +337,16 @@ bool Prefab::tryImportDefaultPrefabs(QWidget * parent, BaseGameVersion version,
|
||||
return false;
|
||||
}
|
||||
|
||||
ParseUtil parser;
|
||||
QString content;
|
||||
switch (version) {
|
||||
case BaseGameVersion::pokeruby:
|
||||
content = parser.readTextFile(":/text/prefabs_default_ruby.json");
|
||||
content = ParseUtil::readTextFile(":/text/prefabs_default_ruby.json");
|
||||
break;
|
||||
case BaseGameVersion::pokefirered:
|
||||
content = parser.readTextFile(":/text/prefabs_default_firered.json");
|
||||
content = ParseUtil::readTextFile(":/text/prefabs_default_firered.json");
|
||||
break;
|
||||
case BaseGameVersion::pokeemerald:
|
||||
content = parser.readTextFile(":/text/prefabs_default_emerald.json");
|
||||
content = ParseUtil::readTextFile(":/text/prefabs_default_emerald.json");
|
||||
break;
|
||||
default:
|
||||
content = QString();
|
||||
|
||||
@@ -123,21 +123,17 @@ bool RegionMapEditor::saveRegionMapEntries() {
|
||||
}
|
||||
|
||||
void buildEmeraldDefaults(poryjson::Json &json) {
|
||||
ParseUtil parser;
|
||||
QString emeraldDefault = parser.readTextFile(":/text/region_map_default_emerald.json");
|
||||
QString emeraldDefault = ParseUtil::readTextFile(":/text/region_map_default_emerald.json");
|
||||
json = poryjson::Json::parse(emeraldDefault);
|
||||
}
|
||||
|
||||
void buildRubyDefaults(poryjson::Json &json) {
|
||||
ParseUtil parser;
|
||||
QString emeraldDefault = parser.readTextFile(":/text/region_map_default_ruby.json");
|
||||
QString emeraldDefault = ParseUtil::readTextFile(":/text/region_map_default_ruby.json");
|
||||
json = poryjson::Json::parse(emeraldDefault);
|
||||
}
|
||||
|
||||
void buildFireredDefaults(poryjson::Json &json) {
|
||||
|
||||
ParseUtil parser;
|
||||
QString fireredDefault = parser.readTextFile(":/text/region_map_default_firered.json");
|
||||
QString fireredDefault = ParseUtil::readTextFile(":/text/region_map_default_firered.json");
|
||||
json = poryjson::Json::parse(fireredDefault);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user