Support C tileset data without initializers
This commit is contained in:
parent
31d090f63c
commit
c58162be96
5 changed files with 39 additions and 21 deletions
|
@ -51,7 +51,7 @@ public:
|
||||||
QStringList readCIncbinArray(const QString &filename, const QString &label);
|
QStringList readCIncbinArray(const QString &filename, const QString &label);
|
||||||
QMap<QString, int> readCDefines(const QString &filename, const QStringList &prefixes, QMap<QString, int> = { });
|
QMap<QString, int> readCDefines(const QString &filename, const QStringList &prefixes, QMap<QString, int> = { });
|
||||||
QStringList readCDefinesSorted(const QString&, const QStringList&, const QMap<QString, int>& = { });
|
QStringList readCDefinesSorted(const QString&, const QStringList&, const QMap<QString, int>& = { });
|
||||||
QMap<QString, QMap<QString, QString>> readCStructs(const QString &, const QString & = "", const QHash<int, QString> = { });
|
QMap<QString, QHash<QString, QString>> readCStructs(const QString &, const QString & = "", const QHash<int, QString> = { });
|
||||||
QList<QStringList> getLabelMacros(const QList<QStringList>&, const QString&);
|
QList<QStringList> getLabelMacros(const QList<QStringList>&, const QString&);
|
||||||
QStringList getLabelValues(const QList<QStringList>&, const QString&);
|
QStringList getLabelValues(const QList<QStringList>&, const QString&);
|
||||||
bool tryParseJsonFile(QJsonDocument *out, const QString &filepath);
|
bool tryParseJsonFile(QJsonDocument *out, const QString &filepath);
|
||||||
|
|
|
@ -37,6 +37,7 @@ public:
|
||||||
static QList<QList<QRgb>> getBlockPalettes(Tileset*, Tileset*, bool useTruePalettes = false);
|
static QList<QList<QRgb>> getBlockPalettes(Tileset*, Tileset*, bool useTruePalettes = false);
|
||||||
static QList<QRgb> getPalette(int, Tileset*, Tileset*, bool useTruePalettes = false);
|
static QList<QRgb> getPalette(int, Tileset*, Tileset*, bool useTruePalettes = false);
|
||||||
static bool metatileIsValid(uint16_t metatileId, Tileset *, Tileset *);
|
static bool metatileIsValid(uint16_t metatileId, Tileset *, Tileset *);
|
||||||
|
static QHash<int, QString> getHeaderMemberMap(bool usingAsm);
|
||||||
static QString getExpectedDir(QString tilesetName, bool isSecondary);
|
static QString getExpectedDir(QString tilesetName, bool isSecondary);
|
||||||
QString getExpectedDir();
|
QString getExpectedDir();
|
||||||
bool appendToHeaders(QString root, QString friendlyName, bool usingAsm);
|
bool appendToHeaders(QString root, QString friendlyName, bool usingAsm);
|
||||||
|
|
|
@ -413,16 +413,17 @@ bool ParseUtil::gameStringToBool(QString gameString) {
|
||||||
return num != 0;
|
return num != 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
QMap<QString, QMap<QString, QString>> ParseUtil::readCStructs(const QString &filename, const QString &label, const QHash<int, QString> memberMap) {
|
QMap<QString, QHash<QString, QString>> ParseUtil::readCStructs(const QString &filename, const QString &label, const QHash<int, QString> memberMap) {
|
||||||
QString filePath = this->root + "/" + filename;
|
QString filePath = this->root + "/" + filename;
|
||||||
auto cParser = fex::Parser();
|
auto cParser = fex::Parser();
|
||||||
auto tokens = fex::Lexer().LexFile(filePath.toStdString());
|
auto tokens = fex::Lexer().LexFile(filePath.toStdString());
|
||||||
auto structs = cParser.ParseTopLevelObjects(tokens);
|
auto structs = cParser.ParseTopLevelObjects(tokens);
|
||||||
QMap<QString, QMap<QString, QString>> structMaps;
|
QMap<QString, QHash<QString, QString>> structMaps;
|
||||||
for (auto it = structs.begin(); it != structs.end(); it++) {
|
for (auto it = structs.begin(); it != structs.end(); it++) {
|
||||||
QString structLabel = QString::fromStdString(it->first);
|
QString structLabel = QString::fromStdString(it->first);
|
||||||
|
if (structLabel.isEmpty()) continue;
|
||||||
if (!label.isEmpty() && label != structLabel) continue; // Speed up parsing if only looking for a particular symbol
|
if (!label.isEmpty() && label != structLabel) continue; // Speed up parsing if only looking for a particular symbol
|
||||||
QMap<QString, QString> values;
|
QHash<QString, QString> values;
|
||||||
int i = 0;
|
int i = 0;
|
||||||
for (const fex::ArrayValue &v : it->second.values()) {
|
for (const fex::ArrayValue &v : it->second.values()) {
|
||||||
if (v.type() == fex::ArrayValue::Type::kValuePair) {
|
if (v.type() == fex::ArrayValue::Type::kValuePair) {
|
||||||
|
@ -430,7 +431,7 @@ QMap<QString, QMap<QString, QString>> ParseUtil::readCStructs(const QString &fil
|
||||||
QString value = QString::fromStdString(v.pair().second->string_value());
|
QString value = QString::fromStdString(v.pair().second->string_value());
|
||||||
values.insert(key, value);
|
values.insert(key, value);
|
||||||
} else {
|
} else {
|
||||||
// For backwards compatibility with structs that don't specify member names.
|
// For compatibility with structs that don't specify member names.
|
||||||
if (memberMap.contains(i))
|
if (memberMap.contains(i))
|
||||||
values.insert(memberMap.value(i), QString::fromStdString(v.string_value()));
|
values.insert(memberMap.value(i), QString::fromStdString(v.string_value()));
|
||||||
}
|
}
|
||||||
|
|
|
@ -255,3 +255,23 @@ QString Tileset::getExpectedDir(QString tilesetName, bool isSecondary)
|
||||||
const QString basePath = projectConfig.getFilePath(ProjectFilePath::data_tilesets_folders) + category + "/";
|
const QString basePath = projectConfig.getFilePath(ProjectFilePath::data_tilesets_folders) + category + "/";
|
||||||
return basePath + tilesetName.replace("gTileset_", "").replace(re, "\\1_\\2").toLower();
|
return basePath + tilesetName.replace("gTileset_", "").replace(re, "\\1_\\2").toLower();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Get the expected positions of the members in struct Tileset.
|
||||||
|
// Used when parsing asm tileset data, or C tileset data that's missing initializers.
|
||||||
|
QHash<int, QString> Tileset::getHeaderMemberMap(bool usingAsm)
|
||||||
|
{
|
||||||
|
// The asm header has a padding field that needs to be skipped
|
||||||
|
int paddingOffset = usingAsm ? 1 : 0;
|
||||||
|
|
||||||
|
// The position of metatileAttributes changes between games
|
||||||
|
bool isPokefirered = (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered);
|
||||||
|
int metatileAttrPosition = (isPokefirered ? 6 : 5) + paddingOffset;
|
||||||
|
|
||||||
|
auto map = QHash<int, QString>();
|
||||||
|
map.insert(1, "isSecondary");
|
||||||
|
map.insert(2 + paddingOffset, "tiles");
|
||||||
|
map.insert(3 + paddingOffset, "palettes");
|
||||||
|
map.insert(4 + paddingOffset, "metatiles");
|
||||||
|
map.insert(metatileAttrPosition, "metatileAttributes");
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
|
@ -1131,6 +1131,7 @@ bool Project::loadLayoutTilesets(MapLayout *layout) {
|
||||||
}
|
}
|
||||||
|
|
||||||
Tileset* Project::loadTileset(QString label, Tileset *tileset) {
|
Tileset* Project::loadTileset(QString label, Tileset *tileset) {
|
||||||
|
auto memberMap = Tileset::getHeaderMemberMap(this->usingAsmTilesets);
|
||||||
if (this->usingAsmTilesets) {
|
if (this->usingAsmTilesets) {
|
||||||
// Read asm tileset header. Backwards compatibility
|
// Read asm tileset header. Backwards compatibility
|
||||||
const QStringList values = parser.getLabelValues(parser.parseAsm(projectConfig.getFilePath(ProjectFilePath::tilesets_headers_asm)), label);
|
const QStringList values = parser.getLabelValues(parser.parseAsm(projectConfig.getFilePath(ProjectFilePath::tilesets_headers_asm)), label);
|
||||||
|
@ -1140,27 +1141,22 @@ Tileset* Project::loadTileset(QString label, Tileset *tileset) {
|
||||||
if (tileset == nullptr) {
|
if (tileset == nullptr) {
|
||||||
tileset = new Tileset;
|
tileset = new Tileset;
|
||||||
}
|
}
|
||||||
// Skips 0 (isCompressed), 2 (padding), and 6/7 (callback)
|
|
||||||
tileset->name = label;
|
tileset->name = label;
|
||||||
tileset->is_secondary = values.value(1);
|
tileset->is_secondary = values.value(memberMap.key("isSecondary"));
|
||||||
tileset->tiles_label = values.value(3);
|
tileset->tiles_label = values.value(memberMap.key("tiles"));
|
||||||
tileset->palettes_label = values.value(4);
|
tileset->palettes_label = values.value(memberMap.key("palettes"));
|
||||||
tileset->metatiles_label = values.value(5);
|
tileset->metatiles_label = values.value(memberMap.key("metatiles"));
|
||||||
if (projectConfig.getBaseGameVersion() == BaseGameVersion::pokefirered) {
|
tileset->metatile_attrs_label = values.value(memberMap.key("metatileAttributes"));
|
||||||
tileset->metatile_attrs_label = values.value(7);
|
|
||||||
} else {
|
|
||||||
tileset->metatile_attrs_label = values.value(6);
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
// Read C tileset header
|
// Read C tileset header
|
||||||
QMap<QString, QMap<QString, QString>> structs = parser.readCStructs(projectConfig.getFilePath(ProjectFilePath::tilesets_headers), label);
|
const auto structs = parser.readCStructs(projectConfig.getFilePath(ProjectFilePath::tilesets_headers), label, memberMap);
|
||||||
if (!structs.contains(label)) {
|
if (!structs.contains(label)) {
|
||||||
return nullptr;
|
return nullptr;
|
||||||
}
|
}
|
||||||
if (tileset == nullptr) {
|
if (tileset == nullptr) {
|
||||||
tileset = new Tileset;
|
tileset = new Tileset;
|
||||||
}
|
}
|
||||||
QMap<QString, QString> tilesetAttributes = structs[label];
|
const auto tilesetAttributes = structs[label];
|
||||||
tileset->name = label;
|
tileset->name = label;
|
||||||
tileset->is_secondary = tilesetAttributes.value("isSecondary");
|
tileset->is_secondary = tilesetAttributes.value("isSecondary");
|
||||||
tileset->tiles_label = tilesetAttributes.value("tiles");
|
tileset->tiles_label = tilesetAttributes.value("tiles");
|
||||||
|
@ -1967,7 +1963,7 @@ bool Project::readTilesetLabels() {
|
||||||
filename = asm_filename; // For error reporting further down
|
filename = asm_filename; // For error reporting further down
|
||||||
} else {
|
} else {
|
||||||
this->usingAsmTilesets = false;
|
this->usingAsmTilesets = false;
|
||||||
QMap<QString, QMap<QString, QString>> structs = parser.readCStructs(filename);
|
const auto structs = parser.readCStructs(filename, "", Tileset::getHeaderMemberMap(this->usingAsmTilesets));
|
||||||
QStringList labels = structs.keys();
|
QStringList labels = structs.keys();
|
||||||
for (const auto tilesetLabel : labels) {
|
for (const auto tilesetLabel : labels) {
|
||||||
if (tilesetLabel.isEmpty()) continue;
|
if (tilesetLabel.isEmpty()) continue;
|
||||||
|
@ -1975,7 +1971,7 @@ bool Project::readTilesetLabels() {
|
||||||
this->tilesetLabels["secondary"].append(tilesetLabel);
|
this->tilesetLabels["secondary"].append(tilesetLabel);
|
||||||
else
|
else
|
||||||
this->tilesetLabels["primary"].append(tilesetLabel);
|
this->tilesetLabels["primary"].append(tilesetLabel);
|
||||||
this->tilesetLabelsOrdered.append(tilesetLabel);
|
this->tilesetLabelsOrdered.append(tilesetLabel); // TODO: This is alphabetical, AdvanceMap import wants the vanilla order
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2534,7 +2530,7 @@ bool Project::readEventGraphics() {
|
||||||
};
|
};
|
||||||
|
|
||||||
QString filepath = projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_info);
|
QString filepath = projectConfig.getFilePath(ProjectFilePath::data_obj_event_gfx_info);
|
||||||
QMap<QString, QMap<QString, QString>> gfxInfos = parser.readCStructs(filepath, "", gfxInfoMemberMap);
|
const auto gfxInfos = parser.readCStructs(filepath, "", gfxInfoMemberMap);
|
||||||
for (QString gfxName : gfxNames) {
|
for (QString gfxName : gfxNames) {
|
||||||
EventGraphics * eventGraphics = new EventGraphics;
|
EventGraphics * eventGraphics = new EventGraphics;
|
||||||
|
|
||||||
|
@ -2542,7 +2538,7 @@ bool Project::readEventGraphics() {
|
||||||
if (!gfxInfos.contains(info_label))
|
if (!gfxInfos.contains(info_label))
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
QMap<QString, QString>gfxInfoAttributes = gfxInfos[info_label];
|
const auto gfxInfoAttributes = gfxInfos[info_label];
|
||||||
|
|
||||||
eventGraphics->inanimate = ParseUtil::gameStringToBool(gfxInfoAttributes.value("inanimate"));
|
eventGraphics->inanimate = ParseUtil::gameStringToBool(gfxInfoAttributes.value("inanimate"));
|
||||||
QString pic_label = gfxInfoAttributes.value("images");
|
QString pic_label = gfxInfoAttributes.value("images");
|
||||||
|
|
Loading…
Reference in a new issue