diff -Nru makoureactor-1.7.2/appveyor.yml makoureactor-1.8.0/appveyor.yml --- makoureactor-1.7.2/appveyor.yml 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/appveyor.yml 2020-08-08 18:46:56.000000000 +0000 @@ -1,16 +1,21 @@ +image: Visual Studio 2019 + environment: matrix: - USE_MSVC: 1 - QTDIR: C:\Qt\5.6\msvc2013 + QTDIR: C:\Qt\5.14\msvc2017 + QTTOOLS: C:\Qt\Tools\QtCreator - USE_MINGW: 1 - QTDIR: C:\Qt\5.6\mingw49_32 + QTDIR: C:\Qt\5.14\mingw73_32 + QTTOOLS: C:\Qt\Tools\mingw730_32 install: - - if "%USE_MINGW%"=="1" set PATH=%QTDIR%\bin;C:\Qt\Tools\mingw492_32\bin;%PATH% - - if "%USE_MSVC%"=="1" set PATH=%QTDIR%\bin;C:\Qt\Tools\QtCreator\bin;%PATH% - - '"C:\Program Files (x86)\Microsoft Visual Studio 12.0\VC\vcvarsall.bat"' - - curl -L -o upx.zip http://upx.sourceforge.net/download/upx391w.zip && - 7z e upx.zip *.exe -r + - DIR C:\Qt + - DIR C:\Qt\Tools + - DIR %QTDIR%\.. + - DIR %QTTOOLS% + - set PATH=%QTDIR%\bin;%QTTOOLS%\bin;%PATH% + - '"C:\Program Files (x86)\Microsoft Visual Studio\2019\Community\VC\Auxiliary\Build\vcvars32.bat"' before_build: - qmake -config release Makou_Reactor.pro @@ -37,7 +42,8 @@ description: Description # Mandatory provider: GitHub auth_token: - secure: hC7ZT9txiEAgKU9m2PzmUNe/eDYz1dNPT2DketUKF+8CwuDiXQgNzKSx33Rek2CF + secure: Q8v2IrepAs+HGD3atYI/0cI52LrxaYzRZKDBaFMSjsz1NPoUrj+Q4lZaZzFaLa4v artifact: /makoureactor-.*\.zip/ on: + branch: develop appveyor_repo_tag: true # deploy on tag push only diff -Nru makoureactor-1.7.2/compat/QtWidgets makoureactor-1.8.0/compat/QtWidgets --- makoureactor-1.7.2/compat/QtWidgets 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/compat/QtWidgets 1970-01-01 00:00:00.000000000 +0000 @@ -1,4 +0,0 @@ -// Compatibility layer for Qt 4 -#include -// QHeaderView changes (incompatibility with Qt 5) -#define setSectionResizeMode setResizeMode diff -Nru makoureactor-1.7.2/core/Archive.cpp makoureactor-1.8.0/core/Archive.cpp --- makoureactor-1.7.2/core/Archive.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/Archive.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -65,8 +65,9 @@ QByteArray Archive::fileData(const QString &filePath) { QIODevice *io = file(filePath); - if(io == NULL || !io->open(QIODevice::ReadOnly)) { - qWarning() << "Archive::fileData error"; + if (io == nullptr || !io->open(QIODevice::ReadOnly)) { + qWarning() << "Archive::fileData error" + << filePath << (io ? io->errorString() : "null"); return QByteArray(); } QByteArray data = io->readAll(); @@ -81,8 +82,9 @@ QByteArray Archive::modifiedFileData(const QString &filePath) { QIODevice *io = modifiedFile(filePath); - if(io == NULL || !io->open(QIODevice::ReadOnly)) { - qWarning() << "Archive::modifiedFileData error"; + if (io == nullptr || !io->open(QIODevice::ReadOnly)) { + qWarning() << "Archive::modifiedFileData error" + << filePath << (io ? io->errorString() : "null"); return QByteArray(); } QByteArray data = io->readAll(); diff -Nru makoureactor-1.7.2/core/Archive.h makoureactor-1.8.0/core/Archive.h --- makoureactor-1.7.2/core/Archive.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/Archive.h 2020-08-08 18:46:56.000000000 +0000 @@ -26,6 +26,7 @@ virtual bool observerWasCanceled() const=0; virtual void setObserverMaximum(unsigned int max)=0; virtual void setObserverValue(int value)=0; + virtual bool observerRetry(const QString &message)=0; }; class Archive @@ -71,7 +72,7 @@ virtual void close(); QString fileName() const; void setFileName(const QString &fileName); - virtual bool pack(const QString &destination=QString(), ArchiveObserver *observer=NULL)=0; + virtual bool pack(const QString &destination=QString(), ArchiveObserver *observer=nullptr)=0; ArchiveError error() const; QString errorString() const; protected: diff -Nru makoureactor-1.7.2/core/Clipboard.cpp makoureactor-1.8.0/core/Clipboard.cpp --- makoureactor-1.7.2/core/Clipboard.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/Clipboard.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -12,7 +12,7 @@ Clipboard *Clipboard::instance() { - if(!_instance) { + if (!_instance) { _instance = new Clipboard(); } @@ -28,7 +28,7 @@ QByteArray Clipboard::data(const QString &mimeType) { const QMimeData *mimeData = QApplication::clipboard()->mimeData(); - if(mimeData && mimeData->hasFormat(mimeType)) { + if (mimeData && mimeData->hasFormat(mimeType)) { return mimeData->data(mimeType); } return QByteArray(); @@ -51,12 +51,12 @@ QList opcodes; QByteArray data = Clipboard::data(MIME_FF7_FIELD_SCRIPT_OPCODES); - if(!data.isEmpty()) { + if (!data.isEmpty()) { QDataStream stream(data); quint16 version; stream >> version; // Check version - if(version != VERSION_FF7_FIELD_SCRIPT_OPCODES) { + if (version != VERSION_FF7_FIELD_SCRIPT_OPCODES) { return opcodes; } stream >> opcodes; @@ -71,6 +71,7 @@ QDataStream stream(&data, QIODevice::WriteOnly); stream << quint16(VERSION_FF7_FIELD_SCRIPT_OPCODES) << opcodes; + setData(MIME_FF7_FIELD_SCRIPT_OPCODES, data); } @@ -84,12 +85,12 @@ QList groups; QByteArray data = Clipboard::data(MIME_FF7_FIELD_SCRIPT_GROUPS); - if(!data.isEmpty()) { + if (!data.isEmpty()) { QDataStream stream(data); quint16 version; stream >> version; // Check version - if(version != VERSION_FF7_FIELD_SCRIPT_GROUPS) { + if (version != VERSION_FF7_FIELD_SCRIPT_GROUPS) { return groups; } stream >> groups; diff -Nru makoureactor-1.7.2/core/Config.cpp makoureactor-1.8.0/core/Config.cpp --- makoureactor-1.7.2/core/Config.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/Config.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -31,7 +31,7 @@ } void Config::set() { - if(!settings) { + if (!settings) { #ifdef Q_OS_WIN settings = new QSettings(qApp->applicationDirPath() .append("/Makou_Reactor.ini"), @@ -46,7 +46,7 @@ } void Config::remove() { - if(settings) delete settings; + if (settings) delete settings; } QVariant Config::value(const QString &key, const QVariant &defaultValue) diff -Nru makoureactor-1.7.2/core/FF7Font.cpp makoureactor-1.8.0/core/FF7Font.cpp --- makoureactor-1.7.2/core/FF7Font.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/FF7Font.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -43,7 +43,7 @@ void FF7Font::setChar(int tableId, int charId, const QString &c) { - if(tableId < _tables.size() && charId < 224) { + if (tableId < _tables.size() && charId < 224) { _tables[tableId][charId] = c; modified = true; } @@ -80,7 +80,7 @@ { _txtPath = txtPath; _windowBinFilePath = windowBinFilePath; - if(_name.isEmpty()) { + if (_name.isEmpty()) { _name = txtPath.mid(txtPath.lastIndexOf('/')+1); _name = _name.left(_name.size() - 4); } @@ -115,28 +115,28 @@ // letterRegExp: "Foo", "Foo","Foo" QStringList table; - if(tableCount < 1) { + if (tableCount < 1) { qWarning() << "invalid windowBinFile!"; return; } - foreach(const QString &line, lines) { - if(line.startsWith("#")) { - if(nameRegExp.indexIn(line) != -1) { + for (const QString &line : qAsConst(lines)) { + if (line.startsWith("#")) { + if (nameRegExp.indexIn(line) != -1) { QStringList capturedTexts = nameRegExp.capturedTexts(); _name = capturedTexts.at(1).trimmed(); } } else { int offset=0; - while((offset = letterRegExp.indexIn(line, offset)) != -1) { + while ((offset = letterRegExp.indexIn(line, offset)) != -1) { QStringList capturedTexts = letterRegExp.capturedTexts(); table.append(capturedTexts.at(1)); offset += capturedTexts.first().size(); - if(table.size() == 224) { + if (table.size() == 224) { _tables.append(table); - if(_tables.size() > tableCount) { + if (_tables.size() > tableCount) { //print(); return; } @@ -146,9 +146,9 @@ } } - if(!table.isEmpty()) { - if(table.size() < 224) { - for(int i=table.size() ; i<224 ; ++i) { + if (!table.isEmpty()) { + if (table.size() < 224) { + for (int i=table.size(); i<224; ++i) { table.append(QString()); } } @@ -163,19 +163,19 @@ { QString data; - if(!_name.isEmpty()) { + if (!_name.isEmpty()) { data.append("#NAME\t").append(_name).append("\n"); } - foreach(const QStringList &t, _tables) { - for(int j=0 ; j<14 ; ++j) { - for(int i=0 ; i<16 ; ++i) { + for (const QStringList &t : qAsConst(_tables)) { + for (int j=0; j<14; ++j) { + for (int i=0; i<16; ++i) { data.append(QString("\"%1\"").arg(t[j*16 + i])); - if(i<15) { + if (i<15) { data.append(","); } } - if(j<13) { + if (j<13) { data.append(","); } data.append("\n"); @@ -190,11 +190,11 @@ void FF7Font::print() { int tid=1; - foreach(const QStringList &t, _tables) { + for (const QStringList &t : _tables) { qDebug() << QString("table %1").arg(tid++).toLatin1().data(); - for(int j=0 ; j<14 ; ++j) { + for (int j=0; j<14; ++j) { QString buf; - for(int i=0 ; i<16 ; ++i) { + for (int i=0; i<16; ++i) { buf += QString("\"%1\",").arg(t[j*16 + i]); } qDebug() << buf.toLatin1().data(); @@ -226,7 +226,7 @@ FF7Font *latinFont = openFont(":/fonts/sysfnt.windowBinFile", ":/fonts/sysfnt.txt"); FF7Font *jpFont = openFont(":/fonts/sysfnt_jp.windowBinFile", ":/fonts/sysfnt_jp.txt"); - if(!latinFont || !jpFont) { + if (!latinFont || !jpFont) { if (latinFont) delete latinFont; if (jpFont) delete jpFont; return false; @@ -238,9 +238,9 @@ fonts.insert("00", latinFont); fonts.insert("01", jpFont); - foreach(const QString &str, stringList) { + for (const QString &str : qAsConst(stringList)) { int index = str.lastIndexOf('.'); - fonts.insert(str.left(index), NULL); + fonts.insert(str.left(index), nullptr); } return true; @@ -253,25 +253,25 @@ FF7Font *FF7Font::openFont(const QString &windowBinFilePath, const QString &txtPath) { - WindowBinFile *windowBinFile = NULL; + WindowBinFile *windowBinFile = nullptr; QFile f(windowBinFilePath); - if(f.open(QIODevice::ReadOnly)) { + if (f.open(QIODevice::ReadOnly)) { windowBinFile = new WindowBinFile(); - if(!windowBinFile->open(f.readAll())) { + if (!windowBinFile->open(f.readAll())) { qWarning() << "Cannot open windowBinFile file!" << f.fileName(); delete windowBinFile; - windowBinFile = NULL; + windowBinFile = nullptr; } f.close(); } - if(!windowBinFile) { - return NULL; + if (!windowBinFile) { + return nullptr; } FF7Font *ff7Font; QFile f2(txtPath); - if(f2.open(QIODevice::ReadOnly)) { + if (f2.open(QIODevice::ReadOnly)) { ff7Font = new FF7Font(windowBinFile, f2.readAll()); f2.close(); } else { @@ -283,15 +283,15 @@ FF7Font *FF7Font::font(QString name) { - if(name.isEmpty()) { + if (name.isEmpty()) { name = "00"; } - if(fonts.contains(name)) { + if (fonts.contains(name)) { FF7Font *ff7Font = fonts.value(name); - if(!ff7Font) { + if (!ff7Font) { ff7Font = openFont(font_dirPath + "/" + name + ".windowBinFile", font_dirPath + "/" + name + ".txt"); - if(!ff7Font) { + if (!ff7Font) { fonts.remove(name);// Bad font, we can remove it } else { fonts.insert(name, ff7Font); @@ -300,7 +300,7 @@ return ff7Font; } - return NULL; + return nullptr; } FF7Font *FF7Font::getCurrentConfigFont() @@ -308,7 +308,7 @@ QString fnt = Config::value("encoding", "00").toString(); QStringList fontL = fontList(); - if(fontL.contains(fnt)) { + if (fontL.contains(fnt)) { return font(fnt); } return font(fontL.first()); @@ -318,20 +318,20 @@ { bool ok = true; - foreach(FF7Font *font, fonts) { - if(font && !font->isReadOnly() && font->isModified()) { + for (FF7Font *font : qAsConst(fonts)) { + if (font && !font->isReadOnly() && font->isModified()) { QFile f1(font->txtPath()); - if(f1.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + if (f1.open(QIODevice::WriteOnly | QIODevice::Truncate)) { f1.write(font->saveTxt().toUtf8()); f1.close(); } else { ok = false; } QFile f2(font->windowBinFilePath()); - if(f2.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + if (f2.open(QIODevice::WriteOnly | QIODevice::Truncate)) { //TODO /*QByteArray tdwData; - if(font->windowBinFile()->save(tdwData)) { + if (font->windowBinFile()->save(tdwData)) { f2.write(tdwData); } else { ok = false; @@ -340,7 +340,7 @@ } else { ok = false; } - if(ok) { + if (ok) { font->setModified(false); } } @@ -349,24 +349,25 @@ return ok; } -bool FF7Font::copyFont(const QString &name, const QString &from, const QString &name2) +bool FF7Font::addFont(const QString &name, const QString &from, + const QString &displayName) { - if(fonts.contains(name) || !fonts.contains(from)) { + if (fonts.contains(name)) { return false; } FF7Font *ff7Font = font(from); - if(!ff7Font) { + if (!ff7Font) { return false; } QFile ftxt(font_dirPath + "/" + name + ".txt"); - if(!ftxt.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + if (!ftxt.open(QIODevice::WriteOnly | QIODevice::Truncate)) { return false; } QFile ftxt2(ff7Font->txtPath()); - if(!ftxt2.open(QIODevice::ReadOnly)) { + if (!ftxt2.open(QIODevice::ReadOnly)) { return false; } @@ -376,12 +377,12 @@ ftxt2.close(); QFile ftdw(font_dirPath + "/" + name + ".windowBinFile"); - if(!ftdw.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + if (!ftdw.open(QIODevice::WriteOnly | QIODevice::Truncate)) { return false; } QFile ftdw2(ff7Font->windowBinFilePath()); - if(!ftdw2.open(QIODevice::ReadOnly)) { + if (!ftdw2.open(QIODevice::ReadOnly)) { return false; } @@ -390,14 +391,14 @@ ftdw.close(); ftdw2.close(); - fonts.insert(name, NULL); + fonts.insert(name, nullptr); ff7Font = font(name); - if(!ff7Font) { + if (!ff7Font) { return false; } - ff7Font->setName(name2); + ff7Font->setName(displayName); ff7Font->setReadOnly(false); return true; @@ -408,11 +409,11 @@ FF7Font *ff7Font = font(name); - if(!ff7Font || ff7Font->isReadOnly()) { + if (!ff7Font || ff7Font->isReadOnly()) { return false; } - if(!QFile::remove(ff7Font->txtPath()) + if (!QFile::remove(ff7Font->txtPath()) || !QFile::remove(ff7Font->windowBinFilePath())) { return false; } diff -Nru makoureactor-1.7.2/core/FF7Font.h makoureactor-1.8.0/core/FF7Font.h --- makoureactor-1.7.2/core/FF7Font.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/FF7Font.h 2020-08-08 18:46:56.000000000 +0000 @@ -45,7 +45,7 @@ static FF7Font *font(QString name); static FF7Font *getCurrentConfigFont(); static bool saveFonts(); - static bool copyFont(const QString &name, const QString &from, const QString &name2); + static bool addFont(const QString &name, const QString &from, const QString &displayName); static bool removeFont(const QString &name); static const QString &fontDirPath(); private: diff -Nru makoureactor-1.7.2/core/FF7Text.cpp makoureactor-1.8.0/core/FF7Text.cpp --- makoureactor-1.7.2/core/FF7Text.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/FF7Text.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -40,17 +40,17 @@ // bool jp = Config::value("jp_txt", false).toBool(); int size = _data.size(); - for(quint16 i=0 ; i= 0xd2 && simplified) { + if (index >= 0xd2 && simplified) { character = "¶"; - } else if(character.isEmpty()) { + } else if (character.isEmpty()) { character = simplified ? "¶" : QString("{xfe}{x%1}").arg(index, 2, 16, QChar('0')); } trad.append(character); } else { character = QString(); - if(index >= 0xd2 && !simplified) { + if (index >= 0xd2 && !simplified) { character = getCaract(index, 7); } - if(character.isEmpty()) { + if (character.isEmpty()) { character = simplified ? "¶" : QString("{xfe}{x%1}").arg(index, 2, 16, QChar('0')); } trad.append(character); @@ -161,10 +161,10 @@ break; default: character = getCaract(index, jp ? 2 : 0); - if((index == 0xe0 || index == 0xe1 || index == 0xe7 || index == 0xe8) && simplified) { + if ((index == 0xe0 || index == 0xe1 || index == 0xe7 || index == 0xe8) && simplified) { character = " "; } - else if(character.isEmpty()) { + else if (character.isEmpty()) { character = simplified ? "¶" : QString("{x%1}").arg(index, 2, 16, QChar('0')); } trad.append(character); @@ -184,15 +184,15 @@ _data.clear(); - for(int c=0 ; cread((char *)&header, 36) != 36 + || header.framesCount == 0 + || device()->pos() + header.framesCount * (24 + 12 * header.boneCount) > device()->size()) { + return false; + } + + return true; +} + bool AFile::read(FieldModelAnimation &animation, int maxFrames) const { if (!canRead()) { @@ -31,9 +46,7 @@ AHeader header; PolyVertex rot, trans; - if (device()->read((char *)&header, 36) != 36 - || header.framesCount == 0 - || device()->pos() + header.framesCount * (24 + 12 * header.boneCount) > device()->size()) { + if (!readHeader(header)) { return false; } @@ -56,7 +69,7 @@ QList rotationCoords; for (quint32 j = 0; j < header.boneCount; ++j) { - if(device()->read((char *)&rot, 12) != 12) { + if (device()->read((char *)&rot, 12) != 12) { return false; } rotationCoords.append(rot); diff -Nru makoureactor-1.7.2/core/field/AFile.h makoureactor-1.8.0/core/field/AFile.h --- makoureactor-1.7.2/core/field/AFile.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/AFile.h 2020-08-08 18:46:56.000000000 +0000 @@ -37,6 +37,7 @@ explicit AFile(QIODevice *device); virtual ~AFile() {} + bool readHeader(AHeader &header) const; bool read(FieldModelAnimation &animation, int maxFrames = -1) const; bool write(const FieldModelAnimation &animation) const; }; diff -Nru makoureactor-1.7.2/core/field/BackgroundFile.cpp makoureactor-1.8.0/core/field/BackgroundFile.cpp --- makoureactor-1.7.2/core/field/BackgroundFile.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/BackgroundFile.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -32,7 +32,7 @@ BackgroundFile::~BackgroundFile() { qDeleteAll(_palettes); - if(_textures) { + if (_textures) { delete _textures; } } @@ -41,28 +41,33 @@ { qDeleteAll(_palettes); _palettes.clear(); - if(_textures) { + if (_textures) { delete _textures; _textures = 0; } _tiles.clear(); } +void BackgroundFile::initEmpty() +{ + +} + QImage BackgroundFile::openBackground(bool *warning) { // Search default background params QHash paramActifs; qint16 z[] = {-1, -1}; field()->scriptsAndTexts()->bgParamAndBgMove(paramActifs, z); - return openBackground(paramActifs, z, NULL, NULL, warning); + return openBackground(paramActifs, z, nullptr, nullptr, warning); } QImage BackgroundFile::openBackground(const QHash ¶mActifs, const qint16 *z, const bool *layers, const QSet *IDs, bool *warning) { - if(!isOpen() && !open()) { - if(warning) { + if (!isOpen() && !open()) { + if (warning) { *warning = false; } return QImage(); @@ -73,8 +78,8 @@ QImage BackgroundFile::backgroundPart(quint16 ID, bool *warning) { - if(!isOpen() && !open()) { - if(warning) { + if (!isOpen() && !open()) { + if (warning) { *warning = false; } return QImage(); @@ -85,8 +90,8 @@ QImage BackgroundFile::drawBackground(const BackgroundTiles &tiles, bool *warning) const { - if(tiles.isEmpty() || !_textures) { - if(warning) { + if (tiles.isEmpty() || !_textures) { + if (warning) { *warning = false; } return QImage(); @@ -102,11 +107,11 @@ QRgb *pixels = (QRgb *)image.bits(); bool warned = false; // To prevent verbosity of warnings - foreach(const Tile &tile, tiles) { + for (const Tile &tile : tiles) { QVector indexOrColorList = _textures->tile(tile); - if(indexOrColorList.isEmpty()) { - if(!warned) { + if (indexOrColorList.isEmpty()) { + if (!warned) { qWarning() << "Texture ID overflow" << tile.textureID << tile.textureID2; warned = true; } @@ -116,17 +121,17 @@ quint8 depth = _textures->depth(tile); Palette *palette = 0; - if(depth <= 1) { - if(tile.paletteID >= _palettes.size()) { - if(!warned) { + if (depth <= 1) { + if (tile.paletteID >= _palettes.size()) { + if (!warned) { qWarning() << "Palette ID overflow" << tile.paletteID << _palettes.size(); warned = true; } continue; } palette = _palettes.at(tile.paletteID); - } else if(depth != 2) { - if(!warned) { + } else if (depth != 2) { + if (!warned) { qWarning() << "Unknown depth" << _textures->depth(tile); warned = true; } @@ -137,14 +142,14 @@ quint32 top = (minHeight + tile.dstY) * width; quint16 baseX = minWidth + tile.dstX; - foreach(uint indexOrColor, indexOrColorList) { - if(!palette) { - if(indexOrColor != 0) { + for (uint indexOrColor : qAsConst(indexOrColorList)) { + if (!palette) { + if (indexOrColor != 0) { pixels[baseX + right + top] = indexOrColor; } } else { - if(palette->notZero(indexOrColor)) { - if(tile.blending) { + if (palette->notZero(indexOrColor)) { + if (tile.blending) { pixels[baseX + right + top] = blendColor(tile.typeTrans, pixels[baseX + right + top], palette->color(indexOrColor)); @@ -154,7 +159,7 @@ } } - if(++right == tile.size) { + if (++right == tile.size) { right = 0; top += width; } @@ -170,7 +175,7 @@ bool BackgroundFile::usedParams(QHash &usedParams, bool *layerExists, QSet *usedIDs) { - if(!isOpen() && !open()) { + if (!isOpen() && !open()) { return false; } @@ -181,11 +186,11 @@ bool BackgroundFile::layerExists(int num) { - if(num == 0) { + if (num == 0) { return true; } - if(!isOpen() && !open()) { + if (!isOpen() && !open()) { return false; } @@ -199,30 +204,30 @@ { int r, g, b; - switch(type) { + switch (type) { case 1: r = qRed(color0) + qRed(color1); - if(r>255) r = 255; + if (r>255) r = 255; g = qGreen(color0) + qGreen(color1); - if(g>255) g = 255; + if (g>255) g = 255; b = qBlue(color0) + qBlue(color1); - if(b>255) b = 255; + if (b>255) b = 255; break; case 2: r = qRed(color0) - qRed(color1); - if(r<0) r = 0; + if (r<0) r = 0; g = qGreen(color0) - qGreen(color1); - if(g<0) g = 0; + if (g<0) g = 0; b = qBlue(color0) - qBlue(color1); - if(b<0) b = 0; + if (b<0) b = 0; break; case 3: r = qRed(color0) + 0.25*qRed(color1); - if(r>255) r = 255; + if (r>255) r = 255; g = qGreen(color0) + 0.25*qGreen(color1); - if(g>255) g = 255; + if (g>255) g = 255; b = qBlue(color0) + 0.25*qBlue(color1); - if(b>255) b = 255; + if (b>255) b = 255; break; default://0 r = (qRed(color0) + qRed(color1))/2; diff -Nru makoureactor-1.7.2/core/field/BackgroundFile.h makoureactor-1.8.0/core/field/BackgroundFile.h --- makoureactor-1.7.2/core/field/BackgroundFile.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/BackgroundFile.h 2020-08-08 18:46:56.000000000 +0000 @@ -32,16 +32,17 @@ BackgroundFile(const BackgroundFile &other); virtual ~BackgroundFile(); + virtual void initEmpty(); using FieldPart::open; using FieldPart::save; virtual inline bool canSave() const { return false; } void clear(); - QImage openBackground(bool *warning = NULL); + QImage openBackground(bool *warning = nullptr); QImage openBackground(const QHash ¶mActifs, const qint16 z[2], - const bool *layers = NULL, const QSet *IDs = NULL, - bool *warning = NULL); + const bool *layers = nullptr, const QSet *IDs = nullptr, + bool *warning = nullptr); // Draw background tiles with ID - QImage backgroundPart(quint16 ID, bool *warning = NULL); + QImage backgroundPart(quint16 ID, bool *warning = nullptr); bool usedParams(QHash &usedParams, bool *layerExists, QSet *usedIDs); bool layerExists(int num); @@ -60,11 +61,11 @@ _palettes = palettes; } - inline BackgroundTextures *textures() const { + inline virtual BackgroundTextures *textures() const { return _textures; } inline void setTextures(BackgroundTextures *textures) { - if(_textures) { + if (_textures) { delete _textures; } _textures = textures; @@ -75,7 +76,7 @@ } protected: - QImage drawBackground(const BackgroundTiles &tiles, bool *warning = NULL) const; + QImage drawBackground(const BackgroundTiles &tiles, bool *warning = nullptr) const; static QRgb blendColor(quint8 type, QRgb color0, QRgb color1); inline BackgroundTiles &tilesRef() { return _tiles; diff -Nru makoureactor-1.7.2/core/field/BackgroundFilePC.cpp makoureactor-1.8.0/core/field/BackgroundFilePC.cpp --- makoureactor-1.7.2/core/field/BackgroundFilePC.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/BackgroundFilePC.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -30,17 +30,56 @@ BackgroundFilePC::BackgroundFilePC(const BackgroundFilePC &other) : BackgroundFile(other) { - setTextures(new BackgroundTexturesPC(*static_cast(other.textures()))); + setTextures(new BackgroundTexturesPC(*other.textures())); PalettesPC palettes; - foreach(Palette *pal, other.palettes()) { + for (Palette *pal : other.palettes()) { palettes.append(new PalettePC(*pal)); } setPalettes(palettes); } +void BackgroundFilePC::initEmpty() +{ + clear(); + + BackgroundTexturesPC *textures = new BackgroundTexturesPC(); + BackgroundTexturesPCInfos infos; + infos.pos = 0; + infos.size = 0; // 16x16 tiles + infos.depth = 2; // No palettes + // Black + textures->setTex(0, QVector(256 * 256, qRgb(0, 0, 0)).toList(), infos); + setTextures(textures); + + quint16 tileID = 0; + QList tiles; + + for (qint16 y = 128; y >= -256; y -= 128) { + for (qint16 dstY = 0; dstY < 128; dstY += 16) { + for (qint16 dstX = -256; dstX < 256; dstX += 16) { + Tile t = Tile(); + t.ID = 4095; + // Data optimization: always the same source + t.srcX = 0; + t.srcY = 0; + t.dstX = dstX; + t.dstY = y + dstY; + t.size = 16; + t.depth = 2; + t.tileID = tileID++; + tiles.append(t); + } + } + } + + setTiles(BackgroundTiles(tiles)); + + BackgroundFile::initEmpty(); +} + bool BackgroundFilePC::open() { - if(isOpen() || isModified()) { + if (isOpen() || isModified()) { setOpen(true); return true; } @@ -57,7 +96,7 @@ palBuff.setData(palData); BackgroundIOPC io(&buff, &palBuff); - if(!io.read(*this)) { + if (!io.read(*this)) { return false; } @@ -71,7 +110,7 @@ QBuffer buff, palBuff; BackgroundIOPC io(&buff, &palBuff); - if(!io.write(*this)) { + if (!io.write(*this)) { return QByteArray(); } @@ -83,7 +122,7 @@ QBuffer buff, palBuff; PaletteIOPC io(&palBuff, &buff); - if(!io.write(palettes())) { + if (!io.write(palettes())) { return QByteArray(); } @@ -94,7 +133,7 @@ { PalettesPS palettesPS = ((PalettesPC *)&palettes())->toPS(); BackgroundTiles tilesPS; - BackgroundTexturesPS texturesPS = (static_cast(textures()))->toPS(tiles(), tilesPS, palettesPS); + BackgroundTexturesPS texturesPS = textures()->toPS(tiles(), tilesPS, palettesPS); BackgroundFilePS filePS(field); filePS.setPalettes(palettesPS); @@ -107,39 +146,60 @@ bool BackgroundFilePC::repair() { - int paletteCount = palettes().size(); + // PC field file contains PS tiles format + // Altough it is unused by the game, we can use it to repair the PC format + BackgroundTilesFile *psTiles = field()->tiles(); + QMap &tiles = (QMap &)tilesRef(); + QMutableMapIterator it(tiles); bool modified = false; - QSet usedPalettes = this->tiles().usedPalettes(); - QList unusedPalettes; + if (psTiles && psTiles->isOpen()) { + const QMap &psTilesList = psTiles->tiles().sortedTiles(); - // List unused palettes - for(int palID = 0; palID < paletteCount; ++palID) { - if(!usedPalettes.contains(palID)) { - unusedPalettes.append(palID); + while (it.hasNext()) { + it.next(); + Tile &tile = it.value(); + const Tile tilePs = psTilesList.value((tile.layerID << 16) | tile.tileID); + + if (tile.depth < 2 && tile.paletteID != tilePs.paletteID) { + tile.paletteID = tilePs.paletteID; + tile.typeTrans = tilePs.typeTrans; + modified = true; + } + } + } else { // By hand + int paletteCount = palettes().size(); + QSet usedPalettes = this->tiles().usedPalettes(); + QList unusedPalettes; + + // List unused palettes + for (int palID = 0; palID < paletteCount; ++palID) { + if (!usedPalettes.contains(palID)) { + unusedPalettes.append(palID); + } } - } - std::sort(unusedPalettes.begin(), unusedPalettes.end(), qLess()); + std::sort(unusedPalettes.begin(), unusedPalettes.end(), std::less()); - QMap &tiles = (QMap &)tilesRef(); - QMap texToPalette; - QMutableMapIterator it(tiles); - while(it.hasNext()) { - it.next(); - Tile &tile = it.value(); - if (tile.depth < 2 && tile.blending && tile.typeTrans != 2 && tile.paletteID >= paletteCount) { - tile.typeTrans = 2; // Modification in place - if(texToPalette.contains(tile.textureID)) { - tile.paletteID = texToPalette.value(tile.textureID); - modified = true; - } else if (!unusedPalettes.isEmpty()) { - tile.paletteID = unusedPalettes.first(); - unusedPalettes.removeFirst(); - texToPalette.insert(tile.textureID, tile.paletteID); - modified = true; - } else { - qWarning() << "BackgroundFilePC::repair cannot detect palette ID to use"; + QMap texToPalette; + + while (it.hasNext()) { + it.next(); + Tile &tile = it.value(); + + if (tile.depth < 2 && tile.blending && tile.typeTrans != 2 && tile.paletteID >= paletteCount) { + tile.typeTrans = 2; // Modification in place + if (texToPalette.contains(tile.textureID)) { + tile.paletteID = texToPalette.value(tile.textureID); + modified = true; + } else if (!unusedPalettes.isEmpty()) { + tile.paletteID = unusedPalettes.first(); + unusedPalettes.removeFirst(); + texToPalette.insert(tile.textureID, tile.paletteID); + modified = true; + } else { + qWarning() << "BackgroundFilePC::repair cannot detect palette ID to use"; + } } } } diff -Nru makoureactor-1.7.2/core/field/BackgroundFilePC.h makoureactor-1.8.0/core/field/BackgroundFilePC.h --- makoureactor-1.7.2/core/field/BackgroundFilePC.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/BackgroundFilePC.h 2020-08-08 18:46:56.000000000 +0000 @@ -35,11 +35,15 @@ explicit BackgroundFilePC(FieldPC *field); BackgroundFilePC(const BackgroundFilePC &other); + void initEmpty(); bool open(); bool open(const QByteArray &data, const QByteArray &palData); QByteArray save() const; QByteArray savePal() const; virtual inline bool canSave() const { return true; } + inline virtual BackgroundTexturesPC *textures() const { + return static_cast(BackgroundFile::textures()); + } BackgroundFilePS toPS(FieldPS *field) const; bool repair(); }; diff -Nru makoureactor-1.7.2/core/field/BackgroundFilePS.cpp makoureactor-1.8.0/core/field/BackgroundFilePS.cpp --- makoureactor-1.7.2/core/field/BackgroundFilePS.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/BackgroundFilePS.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -29,17 +29,24 @@ BackgroundFilePS::BackgroundFilePS(const BackgroundFilePS &other) : BackgroundFile(other) { - setTextures(new BackgroundTexturesPS(*static_cast(other.textures()))); + setTextures(new BackgroundTexturesPS(*other.textures())); PalettesPS palettes; - foreach(Palette *pal, other.palettes()) { + for (Palette *pal : other.palettes()) { palettes.append(new PalettePS(*pal)); } setPalettes(palettes); } +void BackgroundFilePS::initEmpty() +{ + clear(); + setTextures(new BackgroundTexturesPS()); + BackgroundFile::initEmpty(); +} + bool BackgroundFilePS::open() { - if(isOpen() || isModified()) { + if (isOpen() || isModified()) { setOpen(true); return true; } @@ -56,7 +63,7 @@ tilesBuff.setData(tilesData); BackgroundIOPS io(&mimBuff, &tilesBuff); - if(!io.read(*this)) { + if (!io.read(*this)) { return false; } @@ -70,7 +77,7 @@ QBuffer buff, tilesBuff; BackgroundIOPS io(&buff, &tilesBuff); - if(!io.write(*this)) { + if (!io.write(*this)) { return QByteArray(); } @@ -81,7 +88,7 @@ { PalettesPC palettesPC = ((PalettesPS *)&palettes())->toPC(); BackgroundTiles tilesPC; - BackgroundTexturesPC texturesPC = static_cast(textures())->toPC(tiles(), tilesPC, palettesPC); + BackgroundTexturesPC texturesPC = textures()->toPC(tiles(), tilesPC, palettesPC); BackgroundFilePC filePC(field); filePC.setPalettes(palettesPC); diff -Nru makoureactor-1.7.2/core/field/BackgroundFilePS.h makoureactor-1.8.0/core/field/BackgroundFilePS.h --- makoureactor-1.7.2/core/field/BackgroundFilePS.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/BackgroundFilePS.h 2020-08-08 18:46:56.000000000 +0000 @@ -35,9 +35,13 @@ explicit BackgroundFilePS(FieldPS *field); BackgroundFilePS(const BackgroundFilePS &other); + void initEmpty(); bool open(); bool open(const QByteArray &mimData, const QByteArray &tilesData); QByteArray save() const; + inline virtual BackgroundTexturesPS *textures() const { + return static_cast(BackgroundFile::textures()); + } BackgroundFilePC toPC(FieldPC *field) const; }; diff -Nru makoureactor-1.7.2/core/field/BackgroundIO.cpp makoureactor-1.8.0/core/field/BackgroundIO.cpp --- makoureactor-1.7.2/core/field/BackgroundIO.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/BackgroundIO.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -32,8 +32,8 @@ bool BackgroundIOPC::canReadPal() const { - if(_devicePal) { - if(!_devicePal->isOpen()) { + if (_devicePal) { + if (!_devicePal->isOpen()) { return _devicePal->open(QIODevice::ReadOnly); } return _devicePal->isReadable(); @@ -43,8 +43,8 @@ bool BackgroundIOPC::canWritePal() const { - if(_devicePal) { - if(!_devicePal->isOpen()) { + if (_devicePal) { + if (!_devicePal->isOpen()) { return _devicePal->open(QIODevice::WriteOnly); } return _devicePal->isWritable(); @@ -54,13 +54,13 @@ bool BackgroundIOPC::openPalettes(PalettesPC &palettes) const { - if(!_devicePal->reset() || + if (!_devicePal->reset() || !device()->seek(12)) { return false; } PaletteIOPC io(_devicePal, device()); - if(!io.read(palettes)) { + if (!io.read(palettes)) { return false; } @@ -69,12 +69,12 @@ bool BackgroundIOPC::openTiles(BackgroundTiles &tiles) const { - if(!device()->reset()) { + if (!device()->reset()) { return false; } BackgroundTilesIOPC io(device()); - if(!io.read(tiles)) { + if (!io.read(tiles)) { return false; } @@ -83,12 +83,12 @@ bool BackgroundIOPC::openTextures(BackgroundTexturesPC &textures) const { - if(!device()->seek(device()->pos() + 7)) { + if (!device()->seek(device()->pos() + 7)) { return false; } BackgroundTexturesIOPC io(device()); - if(!io.read(&textures)) { + if (!io.read(&textures)) { return false; } @@ -97,7 +97,7 @@ bool BackgroundIOPC::read(BackgroundFile &background) const { - if(!canRead() + if (!canRead() || !canReadPal()) { return false; } @@ -108,7 +108,7 @@ BackgroundTiles tiles; BackgroundTexturesPC textures; - if(!openPalettes(palettes) + if (!openPalettes(palettes) || !openTiles(tiles) || !openTextures(textures)) { qDeleteAll(palettes); @@ -124,7 +124,7 @@ bool BackgroundIOPC::write(const BackgroundFile &background) const { - if(!canWrite() + if (!canWrite() || !canWritePal()) { return false; } @@ -132,7 +132,7 @@ quint16 unknown1 = 0, depth = 1; quint8 unknown2 = 1; - if(device()->write((char *)&unknown1, 2) != 2 + if (device()->write((char *)&unknown1, 2) != 2 || device()->write((char *)&depth, 2) != 2 || device()->write((char *)&unknown2, 1) != 1 || device()->write("PALETTE", 7) != 7) { @@ -140,35 +140,35 @@ } PaletteIOPC paletteIO(devicePal(), device()); - if(!paletteIO.write(background.palettes())) { + if (!paletteIO.write(background.palettes())) { return false; } - if(device()->write("BACK", 4) != 4) { + if (device()->write("BACK", 4) != 4) { return false; } BackgroundTilesIOPC backgroundTiles(device()); - if(!backgroundTiles.write(background.tiles())) { + if (!backgroundTiles.write(background.tiles())) { return false; } - if(device()->write("TEXTURE", 7) != 7) { + if (device()->write("TEXTURE", 7) != 7) { return false; } BackgroundTexturesIOPC backgroundTextures(device()); - if(!backgroundTextures.write(static_cast(background.textures()))) { + if (!backgroundTextures.write(static_cast(background.textures()))) { return false; } - if(device()->write("END", 3) != 3) { + if (device()->write("END", 3) != 3) { return false; } - if(device()->write("FINAL FANTASY7", 14) != 14) { + if (device()->write("FINAL FANTASY7", 14) != 14) { return false; } @@ -182,8 +182,8 @@ bool BackgroundIOPS::canReadTiles() const { - if(_deviceTiles) { - if(!_deviceTiles->isOpen()) { + if (_deviceTiles) { + if (!_deviceTiles->isOpen()) { return _deviceTiles->open(QIODevice::ReadOnly); } return _deviceTiles->isReadable(); @@ -193,8 +193,8 @@ bool BackgroundIOPS::canWriteTiles() const { - if(_deviceTiles) { - if(!_deviceTiles->isOpen()) { + if (_deviceTiles) { + if (!_deviceTiles->isOpen()) { return _deviceTiles->open(QIODevice::WriteOnly); } return _deviceTiles->isWritable(); @@ -204,7 +204,7 @@ bool BackgroundIOPS::openPalettes(PalettesPS &palettes) const { - if(!device()->reset()) { + if (!device()->reset()) { return false; } @@ -213,7 +213,7 @@ bool BackgroundIOPS::openTiles(BackgroundTiles &tiles) const { - if(!deviceTiles()->reset()) { + if (!deviceTiles()->reset()) { return false; } @@ -222,7 +222,7 @@ bool BackgroundIOPS::openTextures(BackgroundTexturesPS &textures) const { - if(!device()->reset()) { + if (!device()->reset()) { return false; } @@ -231,7 +231,7 @@ bool BackgroundIOPS::savePalettes(const Palettes &palettes) const { - if(!device()->reset()) { + if (!device()->reset()) { return false; } @@ -240,7 +240,7 @@ bool BackgroundIOPS::saveTiles(const BackgroundTiles &tiles) const { - if(!deviceTiles()->reset()) { + if (!deviceTiles()->reset()) { return false; } @@ -255,7 +255,7 @@ bool BackgroundIOPS::read(BackgroundFile &background) const { - if(!canRead() + if (!canRead() || !canReadTiles()) { return false; } @@ -264,26 +264,26 @@ PalettesPS palettes; BackgroundTiles tiles; - BackgroundTexturesPS textures; + BackgroundTexturesPS *textures = new BackgroundTexturesPS(); - if(!openPalettes(palettes) + if (!openPalettes(palettes) || !openTiles(tiles) - || !openTextures(textures)) { + || !openTextures(*textures)) { qDeleteAll(palettes); + delete textures; return false; } background.setPalettes(palettes); background.setTiles(tiles); - BackgroundTexturesPS *texPtr = new BackgroundTexturesPS(textures); - background.setTextures(texPtr); + background.setTextures(textures); return true; } bool BackgroundIOPS::write(const BackgroundFile &background) const { - if(!canWrite() + if (!canWrite() || !canWriteTiles()) { return false; } diff -Nru makoureactor-1.7.2/core/field/BackgroundTextures.cpp makoureactor-1.8.0/core/field/BackgroundTextures.cpp --- makoureactor-1.7.2/core/field/BackgroundTextures.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/BackgroundTextures.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -45,7 +45,7 @@ } lastByte = qMin(origin + tile.size * texWidth, maxByte); - for(quint32 i=origin ; i it(_texInfos); - while(it.hasNext()) { + while (it.hasNext()) { it.next(); if(it.value().pos > oldInfos.pos) { @@ -218,10 +218,12 @@ QRgb BackgroundTexturesPC::directColor(quint16 color) const { - return qRgba(qRound(COEFF_COLOR * (color >> 11)), - qRound(COEFF_COLOR * (color >> 6 & 31)), - qRound(COEFF_COLOR * (color & 31)), - color == 0 ? 0 : 255); // special PC RGB16 color + quint8 b = color & 31, + g = (color >> 6) & 31, + r = color >> 11; + + // special PC RGB16 color + return qRgba((r << 3) + (r >> 2), (g << 3) + (g >> 2), (b << 3) + (b >> 2), color == 0 ? 0 : 255); } quint16 BackgroundTexturesPC::toPcColor(const QRgb &color) @@ -240,7 +242,7 @@ img.fill(Qt::black); QRgb *bits = (QRgb *)img.bits(); - foreach(uint indexOrRgb, indexOrRgbList) { + for (uint indexOrRgb : qAsConst(indexOrRgbList)) { if(infos.depth != 2) { *bits = qRgb(indexOrRgb, indexOrRgb, indexOrRgb); } else { @@ -264,7 +266,7 @@ img.fill(Qt::black); QRgb *bits = (QRgb *)img.bits(); - foreach(const Tile &tile, tiles) { + for (const Tile &tile : tiles) { if(tile.textureID == texID) { QVector indexOrRgbList = this->tile(tile); Palette *palette = 0; @@ -275,7 +277,7 @@ palette = palettes.at(tile.paletteID); } - foreach(uint indexOrRgb, indexOrRgbList) { + for (uint indexOrRgb : qAsConst(indexOrRgbList)) { // if(tile.depth == 0) { // bits[pos + y * 256 + x] = qRgb(0, 255, 0); // } else if(tile.depth == 1) { @@ -351,8 +353,8 @@ int curPos; quint16 pageTexW = pageTexWidth(y); - for(int texY=0 ; texY<256 ; ++texY) { - for(int texX=0 ; texX<256 ; ++texX) { + for (int texY=0; texY<256; ++texY) { + for (int texX=0; texX<256; ++texX) { curPos = pos + texY * pageTexW + (depth == 0 ? texX/2 : texX * depth); if(depth == 0) { @@ -417,7 +419,7 @@ { QMap > groupedTextures; - foreach(const Tile &tile, psTiles.sortedTiles()) { + for (const Tile &tile : psTiles.sortedTiles()) { if((tile.textureID2 == 0 && _headerImg.w <= 0) || (tile.textureID2 == 1 && _headerEffect.w <= 0)) { @@ -433,7 +435,7 @@ */ quint8 depthKey = 0; - switch(tile.depth & 3) { + switch (tile.depth & 3) { case 0: depthKey = 1; break; case 1: depthKey = 0; break; default: depthKey = 2; break; @@ -452,7 +454,7 @@ // Detection of transparency PC flag: true if one of used indexes is transparent const QList &areZero = palette->areZero(); - foreach(uint index, tileData) { + for (uint index : qAsConst(tileData)) { if(areZero.at(index)) { palette->setTransparency(true); break; @@ -475,7 +477,7 @@ BackgroundTiles pcTiles2; BackgroundTexturesPC ret; - while(it.hasNext()) { + while (it.hasNext()) { it.next(); QList &texture = it.value(); BackgroundTexturesPCInfos info; @@ -490,7 +492,7 @@ /* On PC version, only the first palette color can be transparent * So we need to change all indexes to a transparent color to 0 * And relocate when index=0 */ - for(int texConvId=0 ; texConvId < texture.size() ; ++texConvId) { + for (int texConvId=0; texConvId < texture.size(); ++texConvId) { BackgroundConversionTexture &tileConversion = texture[texConvId]; if (tileConversion.tile.depth >= 2) { continue; // No palette here @@ -504,7 +506,7 @@ int indexOfFirstZero = areZero.indexOf(true, 1); if(firstIsZero || indexOfFirstZero > -1) { int i = 0; - foreach(uint index, tileConversion.data) { + for (uint index : qAsConst(tileConversion.data)) { if(index > 0 && areZero.at(index)) { // When the index refer to a transparent color, change this index to 0 @@ -533,7 +535,7 @@ QSet usedTextures; usedTextures.reserve(BACKGROUND_TEXTURE_PC_MAX_COUNT); - for(int i=0 ; i flatten; - for(quint8 tileY=0 ; tileYclear(); qint64 initPos = device()->pos(); - for(quint8 texID=0 ; texIDread((char *)&exists, 2) != 2) { + if (device()->read((char *)&exists, 2) != 2) { qWarning() << "BackgroundTexturesIOPC::read cannot read exists" << texID; return false; } - if(bool(exists)) { + if (bool(exists)) { quint16 size, depth; - if(device()->read((char *)&size, 2) != 2 || + if (device()->read((char *)&size, 2) != 2 || device()->read((char *)&depth, 2) != 2) { qWarning() << "BackgroundTexturesIOPC::read cannot read size or depth" << texID; return false; @@ -60,14 +60,14 @@ infos.pos = device()->pos() - initPos; textures->addTexInfos(texID, infos); - if(!device()->seek(device()->pos() + (depth == 0 ? 32768 : depth * 65536))) { + if (!device()->seek(device()->pos() + (depth == 0 ? 32768 : depth * 65536))) { qWarning() << "BackgroundTexturesIOPC::read cannot seek texture" << texID; return false; } } } - if(!device()->seek(initPos)) { + if (!device()->seek(initPos)) { qWarning() << "BackgroundTexturesIOPC::read cannot reset"; return false; } @@ -78,30 +78,31 @@ bool BackgroundTexturesIOPC::write(const BackgroundTexturesPC *textures) const { - if(!canWrite()) { + if (!canWrite() || !textures) { return false; } - for(quint8 texID=0 ; texIDhasTex(texID); - if(device()->write((char *)&exists, 2) != 2) { + if (device()->write((char *)&exists, 2) != 2) { return false; } - if(bool(exists)) { + if (bool(exists)) { BackgroundTexturesPCInfos infos = textures->texInfos(texID); quint16 size = infos.size, depth = infos.depth; - if(device()->write((char *)&size, 2) != 2 || + if (device()->write((char *)&size, 2) != 2 || device()->write((char *)&depth, 2) != 2) { return false; } - if(device()->write(textures->data().mid(infos.pos, infos.depth * 65536)) - != infos.depth * 65536) { + int dataSize = infos.depth == 0 ? 32768 : infos.depth * 65536; + + if (device()->write(textures->data().mid(infos.pos, dataSize)) != dataSize) { return false; } } @@ -117,7 +118,7 @@ bool BackgroundTexturesIOPS::read(BackgroundTexturesPS *textures) const { - if(!canRead()) { + if (!canRead()) { return false; } @@ -128,7 +129,7 @@ memcpy(&headerPalSize, constMimData, 4); - if(mimDataSize < headerPalSize + 12) { + if (mimDataSize < headerPalSize + 12) { return false; } @@ -136,7 +137,7 @@ headerImg.w *= 2; - if(headerPalSize+headerImg.size+12 <= mimDataSize) { + if (headerPalSize+headerImg.size+12 <= mimDataSize) { memcpy(&headerEffect, constMimData + headerPalSize+headerImg.size, 12); headerEffect.w *= 2; } else { @@ -156,7 +157,7 @@ bool BackgroundTexturesIOPS::write(const BackgroundTexturesPS *textures) const { - if(!canWrite()) { + if (!canWrite()) { return false; } diff -Nru makoureactor-1.7.2/core/field/BackgroundTiles.cpp makoureactor-1.8.0/core/field/BackgroundTiles.cpp --- makoureactor-1.7.2/core/field/BackgroundTiles.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/BackgroundTiles.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -24,8 +24,8 @@ BackgroundTiles::BackgroundTiles(const QList &tiles) { - foreach (const Tile &tile, tiles) { - switch(tile.layerID) { + for (const Tile &tile : tiles) { + switch (tile.layerID) { case 0: insert(1, tile); break; @@ -52,28 +52,28 @@ { BackgroundTiles ret; - foreach(const Tile &tile, *this) { - switch(tile.layerID) { + for (const Tile &tile : *this) { + switch (tile.layerID) { case 0: - if((layers == NULL || layers[0]) && (IDs == NULL || IDs->contains(1))) { + if ((layers == nullptr || layers[0]) && (IDs == nullptr || IDs->contains(1))) { ret.insert(1, tile); } break; case 1: - if((tile.state == 0 || paramActifs.value(tile.param, 0) & tile.state) - && (layers == NULL || layers[1]) && (IDs == NULL || IDs->contains(tile.ID))) { + if ((tile.state == 0 || paramActifs.value(tile.param, 0) & tile.state) + && (layers == nullptr || layers[1]) && (IDs == nullptr || IDs->contains(tile.ID))) { ret.insert(4096 - tile.ID, tile); } break; case 2: - if((tile.state == 0 || paramActifs.value(tile.param, 0) & tile.state) - && (layers == NULL || layers[2]) && (IDs == NULL || IDs->contains(tile.ID))) { + if ((tile.state == 0 || paramActifs.value(tile.param, 0) & tile.state) + && (layers == nullptr || layers[2]) && (IDs == nullptr || IDs->contains(tile.ID))) { ret.insert(4096 - ((z && z[0] != -1) ? z[0] : tile.ID), tile); } break; case 3: - if((tile.state == 0 || paramActifs.value(tile.param, 0) & tile.state) - && (layers == NULL || layers[3]) && (IDs == NULL || IDs->contains(tile.ID))) { + if ((tile.state == 0 || paramActifs.value(tile.param, 0) & tile.state) + && (layers == nullptr || layers[3]) && (IDs == nullptr || IDs->contains(tile.ID))) { ret.insert(4096 - ((z && z[1] != -1) ? z[1] : tile.ID), tile); } break; @@ -87,8 +87,8 @@ { BackgroundTiles ret; - foreach(const Tile &tile, *this) { - if(tile.layerID == layerID) { + for (const Tile &tile : *this) { + if (tile.layerID == layerID) { ret.insert(orderedForSaving ? tile.tileID : 4096 - tile.ID, @@ -103,8 +103,8 @@ { BackgroundTiles ret; - foreach(const Tile &tile, *this) { - if(tile.ID == ID) { + for (const Tile &tile : *this) { + if (tile.ID == ID) { ret.insert(orderedForSaving ? tile.tileID : 4096 - tile.ID, @@ -119,8 +119,8 @@ { QMap ret; - foreach(const Tile &tile, *this) { - if(ret.contains((tile.layerID << 16) | tile.tileID)) { + for (const Tile &tile : *this) { + if (ret.contains((tile.layerID << 16) | tile.tileID)) { qWarning() << "BackgroundTiles::sortedTiles() tile not unique!" << tile.layerID << tile.tileID; } ret.insert((tile.layerID << 16) | tile.tileID, tile); @@ -134,28 +134,28 @@ QHash ret; layerExists[0] = layerExists[1] = layerExists[2] = false; - foreach(const Tile &tile, *this) { - switch(tile.layerID) { + for (const Tile &tile : *this) { + switch (tile.layerID) { case 0: break; case 1: layerExists[0] = true; - if(tile.param) { + if (tile.param) { ret.insert(tile.param, ret.value(tile.param) | tile.state); } - if(usedIDs) { + if (usedIDs) { usedIDs->insert(tile.ID); } break; case 2: layerExists[1] = true; - if(tile.param) { + if (tile.param) { ret.insert(tile.param, ret.value(tile.param) | tile.state); } break; case 3: layerExists[2] = true; - if(tile.param) { + if (tile.param) { ret.insert(tile.param, ret.value(tile.param) | tile.state); } break; @@ -169,7 +169,7 @@ { QSet ret; - foreach(const Tile &tile, *this) { + for (const Tile &tile : *this) { if (tile.depth < 2) { ret.insert(tile.paletteID); } @@ -184,15 +184,15 @@ quint16 maxWidth=0, maxHeight=0; minWidth = minHeight = 0; - foreach(const Tile &tile, *this) { + for (const Tile &tile : *this) { quint8 toAdd = tile.size - 16; - if(tile.dstX >= 0 && tile.dstX+toAdd > maxWidth) + if (tile.dstX >= 0 && tile.dstX+toAdd > maxWidth) maxWidth = tile.dstX+toAdd; - else if(tile.dstX < 0 && -tile.dstX > minWidth) + else if (tile.dstX < 0 && -tile.dstX > minWidth) minWidth = -tile.dstX; - if(tile.dstY >= 0 && tile.dstY+toAdd > maxHeight) + if (tile.dstY >= 0 && tile.dstY+toAdd > maxHeight) maxHeight = tile.dstY+toAdd; - else if(tile.dstY < 0 && -tile.dstY > minHeight) + else if (tile.dstY < 0 && -tile.dstY > minHeight) minHeight = -tile.dstY; } @@ -213,8 +213,8 @@ Tile BackgroundTiles::search(quint8 textureID1, quint8 textureID2, quint8 srcX, quint8 srcY) const { - foreach(const Tile &tile, *this) { - if(tile.textureID == textureID1 && + for (const Tile &tile : *this) { + if (tile.textureID == textureID1 && (textureID2 == quint8(-1) || tile.textureID2 == textureID2) && tile.srcX == srcX && tile.srcY == srcY) { @@ -226,3 +226,8 @@ nullTile.tileID = quint16(-1); return nullTile; } + +int operator==(const Tile &tile, const Tile &other) +{ + return memcmp(&tile, &other, sizeof(tile) - 4); +} diff -Nru makoureactor-1.7.2/core/field/BackgroundTilesFile.cpp makoureactor-1.8.0/core/field/BackgroundTilesFile.cpp --- makoureactor-1.7.2/core/field/BackgroundTilesFile.cpp 1970-01-01 00:00:00.000000000 +0000 +++ makoureactor-1.8.0/core/field/BackgroundTilesFile.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -0,0 +1,45 @@ +#include "BackgroundTilesFile.h" +#include "BackgroundTilesIO.h" +#include "Field.h" + +BackgroundTilesFile::BackgroundTilesFile(Field *field) : + FieldPart(field) +{ +} + +BackgroundTilesFile::~BackgroundTilesFile() +{ +} + +bool BackgroundTilesFile::open() +{ + return open(field()->sectionData(Field::Tiles)); +} + +bool BackgroundTilesFile::open(const QByteArray &data) +{ + QBuffer buffer; + buffer.setData(data); + + if (BackgroundTilesIOPS(&buffer).read(_tiles)) { + setOpen(true); + + return true; + } + + return false; +} + +QByteArray BackgroundTilesFile::save() const +{ + QBuffer buffer; + + BackgroundTilesIOPS(&buffer).write(_tiles); + + return buffer.data(); +} + +void BackgroundTilesFile::clear() +{ + _tiles.clear(); +} diff -Nru makoureactor-1.7.2/core/field/BackgroundTilesFile.h makoureactor-1.8.0/core/field/BackgroundTilesFile.h --- makoureactor-1.7.2/core/field/BackgroundTilesFile.h 1970-01-01 00:00:00.000000000 +0000 +++ makoureactor-1.8.0/core/field/BackgroundTilesFile.h 2020-08-08 18:46:56.000000000 +0000 @@ -0,0 +1,28 @@ +#ifndef BACKGROUNDTILESFILE_H +#define BACKGROUNDTILESFILE_H + +#include +#include "FieldPart.h" +#include "BackgroundTiles.h" + +// This class is only used for repairing PC backgrounds +class BackgroundTilesFile : public FieldPart +{ +public: + explicit BackgroundTilesFile(Field *field); + virtual ~BackgroundTilesFile(); + + bool open(); + bool open(const QByteArray &data); + QByteArray save() const; + void clear(); + + inline const BackgroundTiles &tiles() const { + return _tiles; + } + +private: + BackgroundTiles _tiles; +}; + +#endif // BACKGROUNDTILESFILE_H diff -Nru makoureactor-1.7.2/core/field/BackgroundTiles.h makoureactor-1.8.0/core/field/BackgroundTiles.h --- makoureactor-1.7.2/core/field/BackgroundTiles.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/BackgroundTiles.h 2020-08-08 18:46:56.000000000 +0000 @@ -47,7 +47,7 @@ BackgroundTiles tiles(quint8 layerID, bool orderedForSaving = false) const; BackgroundTiles tilesByID(quint16 ID, bool orderedForSaving = false) const; QMap sortedTiles() const; - QHash usedParams(bool *layerExists, QSet *usedIDs = NULL) const; + QHash usedParams(bool *layerExists, QSet *usedIDs = nullptr) const; QSet usedPalettes() const; void area(quint16 &minWidth, quint16 &minHeight, int &width, int &height) const; @@ -55,4 +55,6 @@ Tile search(quint8 textureID1, quint8 textureID2, quint8 srcX, quint8 srcY) const; }; +int operator==(const Tile &tile, const Tile &other); + #endif // BACKGROUNDTILES_H diff -Nru makoureactor-1.7.2/core/field/BackgroundTilesIO.cpp makoureactor-1.8.0/core/field/BackgroundTilesIO.cpp --- makoureactor-1.7.2/core/field/BackgroundTilesIO.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/BackgroundTilesIO.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -24,7 +24,7 @@ bool BackgroundTilesIO::read(BackgroundTiles &tiles) const { - if(!canRead()) { + if (!canRead()) { return false; } @@ -35,7 +35,7 @@ bool BackgroundTilesIO::write(const BackgroundTiles &tiles) const { - if(!canWrite()) { + if (!canWrite()) { return false; } @@ -57,41 +57,41 @@ char exists; const quint8 sizeofTile = sizeof(TilePC); - if(!device()->seek(44)) { + if (!device()->seek(44)) { qWarning() << "BackgroundTilesIOPC::readData device size too short"; return false; } - if(device()->read((char *)&nbTiles1, 2) != 2) { + if (device()->read((char *)&nbTiles1, 2) != 2) { qWarning() << "BackgroundTilesIOPC::readData cannot read nbTiles1"; return false; } - if(!device()->seek(52)) { + if (!device()->seek(52)) { qWarning() << "BackgroundTilesIOPC::readData cannot seek (1)"; return false; } - if(nbTiles1 > 0) { + if (nbTiles1 > 0) { data = device()->read(nbTiles1 * 52 - 52 + sizeofTile); - if(data.size() != nbTiles1 * 52 - 52 + sizeofTile) { + if (data.size() != nbTiles1 * 52 - 52 + sizeofTile) { qWarning() << "BackgroundTilesIOPC::readData cannot read tiles data (1)"; return false; } // BG 0 - for(i=0 ; iseek(52 + nbTiles1 * 52)) { + if (!device()->seek(52 + nbTiles1 * 52)) { qWarning() << "BackgroundTilesIOPC::readData cannot seek (2)"; return false; } @@ -99,50 +99,50 @@ cur = device()->pos(); - if(!device()->getChar(&exists)) { + if (!device()->getChar(&exists)) { qWarning() << "BackgroundTilesIOPC::readData cannot read exists2"; return false; } // BG 1 - if(bool(exists)) { + if (bool(exists)) { - if(!device()->seek(cur + 5)) { + if (!device()->seek(cur + 5)) { qWarning() << "BackgroundTilesIOPC::readData cannot seek (3)"; return false; } - if(device()->read((char *)&nbTiles2, 2) != 2) { + if (device()->read((char *)&nbTiles2, 2) != 2) { qWarning() << "BackgroundTilesIOPC::readData cannot read nbTiles2"; return false; } - if(nbTiles2 > 0) { + if (nbTiles2 > 0) { - if(!device()->seek(cur + 27)) { + if (!device()->seek(cur + 27)) { qWarning() << "BackgroundTilesIOPC::readData cannot seek (4)"; return false; } data = device()->read(nbTiles2 * 52 - 52 + sizeofTile); - if(data.size() != nbTiles2 * 52 - 52 + sizeofTile) { + if (data.size() != nbTiles2 * 52 - 52 + sizeofTile) { qWarning() << "BackgroundTilesIOPC::readData cannot read tiles data (2)"; return false; } - for(i=0 ; iseek(cur + 27 + nbTiles2 * 52)) { + if (!device()->seek(cur + 27 + nbTiles2 * 52)) { qWarning() << "BackgroundTilesIOPC::readData cannot seek (5)"; return false; } @@ -150,51 +150,51 @@ cur = device()->pos(); - if(!device()->getChar(&exists)) { + if (!device()->getChar(&exists)) { qWarning() << "BackgroundTilesIOPC::readData cannot read exists3"; return false; } // BG 2 - if(bool(exists)) { + if (bool(exists)) { - if(!device()->seek(cur + 5)) { + if (!device()->seek(cur + 5)) { qWarning() << "BackgroundTilesIOPC::readData cannot seek (6)"; return false; } - if(device()->read((char *)&nbTiles3, 2) != 2) { + if (device()->read((char *)&nbTiles3, 2) != 2) { qWarning() << "BackgroundTilesIOPC::readData cannot read nbTiles3"; return false; } - if(nbTiles3 > 0) { + if (nbTiles3 > 0) { - if(!device()->seek(cur + 21)) { + if (!device()->seek(cur + 21)) { qWarning() << "BackgroundTilesIOPC::readData cannot seek (7)"; return false; } data = device()->read(nbTiles3 * 52 - 52 + sizeofTile); - if(data.size() != nbTiles3 * 52 - 52 + sizeofTile) { + if (data.size() != nbTiles3 * 52 - 52 + sizeofTile) { qWarning() << "BackgroundTilesIOPC::readData cannot read tiles data (3)"; return false; } - for(i=0 ; iseek(cur + 21 + nbTiles3 * 52)) { + if (!device()->seek(cur + 21 + nbTiles3 * 52)) { qWarning() << "BackgroundTilesIOPC::readData cannot seek (8)"; return false; } @@ -202,50 +202,50 @@ cur = device()->pos(); - if(!device()->getChar(&exists)) { + if (!device()->getChar(&exists)) { qWarning() << "BackgroundTilesIOPC::readData cannot read exists4"; return false; } // BG 3 - if(bool(exists)) { + if (bool(exists)) { - if(!device()->seek(cur + 5)) { + if (!device()->seek(cur + 5)) { qWarning() << "BackgroundTilesIOPC::readData cannot seek (9)"; return false; } - if(device()->read((char *)&nbTiles4, 2) != 2) { + if (device()->read((char *)&nbTiles4, 2) != 2) { qWarning() << "BackgroundTilesIOPC::readData cannot read nbTiles4"; return false; } - if(nbTiles4 > 0) { + if (nbTiles4 > 0) { - if(!device()->seek(cur + 21)) { + if (!device()->seek(cur + 21)) { qWarning() << "BackgroundTilesIOPC::readData cannot seek (10)"; return false; } data = device()->read(nbTiles4 * 52 - 52 + sizeofTile); - if(data.size() != nbTiles4 * 52 - 52 + sizeofTile) { + if (data.size() != nbTiles4 * 52 - 52 + sizeofTile) { qWarning() << "BackgroundTilesIOPC::readData cannot read tiles data (4)"; return false; } - for(i=0 ; iseek(cur + 21 + nbTiles4 * 52)) { + if (!device()->seek(cur + 21 + nbTiles4 * 52)) { qWarning() << "BackgroundTilesIOPC::readData cannot seek (11)"; return false; } @@ -291,7 +291,7 @@ device()->write((char *)&depth, 2); device()->write("\0\0", 2); - foreach(const Tile &tile, tiles1) { + for (const Tile &tile : qAsConst(tiles1)) { writeTile(tile); } @@ -304,7 +304,7 @@ BackgroundTiles tiles2 = tiles.tiles(1, true); - if(!tiles2.isEmpty()) { + if (!tiles2.isEmpty()) { nbTiles = tiles2.size(); device()->putChar('\x01'); @@ -314,7 +314,7 @@ device()->write(QByteArray(16, '\0')); // Unknown but unused device()->write("\0\0", 2); - foreach(const Tile &tile, tiles2) { + for (const Tile &tile : qAsConst(tiles2)) { writeTile(tile); } @@ -327,7 +327,7 @@ BackgroundTiles tiles3 = tiles.tiles(2, true); - if(!tiles3.isEmpty()) { + if (!tiles3.isEmpty()) { nbTiles = tiles3.size(); device()->putChar('\x01'); @@ -337,7 +337,7 @@ device()->write(QByteArray(10, '\0')); device()->write("\0\0", 2); - foreach(const Tile &tile, tiles3) { + for (const Tile &tile : qAsConst(tiles3)) { writeTile(tile); } @@ -350,7 +350,7 @@ BackgroundTiles tiles4 = tiles.tiles(3, true); - if(!tiles4.isEmpty()) { + if (!tiles4.isEmpty()) { nbTiles = tiles4.size(); device()->putChar('\x01'); @@ -360,7 +360,7 @@ device()->write(QByteArray(10, '\0')); // Unknown but unused device()->write("\0\0", 2); - foreach(const Tile &tile, tiles4) { + for (const Tile &tile : qAsConst(tiles4)) { writeTile(tile); } @@ -376,7 +376,7 @@ { Tile ret; - if(layerID > 0 && tile.textureID2 > 0) { + if (layerID > 0 && tile.textureID2 > 0) { ret.srcX = tile.srcX2; ret.srcY = tile.srcY2; ret.textureID = tile.textureID2; @@ -388,14 +388,14 @@ ret.dstX = tile.dstX; ret.dstY = tile.dstY; ret.paletteID = tile.paletteID; - if(layerID > 0) { + if (layerID > 0) { ret.param = tile.param; ret.state = tile.state; ret.blending = tile.blending; } else { ret.param = ret.state = ret.blending = 0; } - switch(layerID) { + switch (layerID) { case 0: ret.ID = 4095; break; case 2: ret.ID = 4096; break; case 3: ret.ID = 0; break; @@ -452,7 +452,7 @@ qint64 i; bool isDemoFormat = _demo; - if(datDataSize < 16) { + if (datDataSize < 16) { return false; } @@ -481,8 +481,8 @@ quint8 layerID=0; i = isDemoFormat ? 12 : 16; - while(i < start1) { - if(start1 < i+2) { + while (i < start1) { + if (start1 < i+2) { return false; } @@ -490,12 +490,12 @@ memcpy(&type, constDatData + i, 2); - if(type == 0x7FFF) { + if (type == 0x7FFF) { nbTilesLayer.append(tilePos + tileCount); ++layerID; } else { - if(type == 0x7FFE) { - if(i - 4 < 16) { + if (type == 0x7FFE) { + if (i - 4 < 16) { qWarning() << "BackgroundTilesIOPS::readData 0x7FFE positionned too early"; return false; } @@ -505,7 +505,7 @@ nbTilesTex.append(tilePos + tileCount); } else { - if(start1 < i+6) { + if (start1 < i+6) { return false; } @@ -532,7 +532,7 @@ qWarning() << "BackgroundTilesIOPS::open padding after (1)" << ((start3-start2) % 2); } - for(i=0 ; i> 6) & 0xF; - if(texID+1=nbTilesTex.at(texID)) { + if (texID+1=nbTilesTex.at(texID)) { ++texID; tile2 = tiles2.at(texID); } @@ -590,9 +590,9 @@ qWarning() << "BackgroundTilesIOPS::open padding after (3)" << ((start4-start3) % 14); } - for(i=0 ; i= 4095) { + tile.IDBig = 9998999; } else { // FIXME: approximation - tile.IDBig = quint32((float(tile.ID) / 4096.0f) * 10000000.0f + i); + tile.IDBig = quint32((float(tile.ID) / 4096.0f) * 10000000.0f); } tiles.insert(4096 - tile.ID, tile); @@ -644,9 +646,9 @@ quint32 j=0; - for(i=0 ; i=nbTilesTex.at(texID)) { + if (texID+1=nbTilesTex.at(texID)) { ++texID; tile2 = tiles2.at(texID); } - if(layerID+1=nbTilesLayer.at(layerID)) { + if (layerID+1=nbTilesLayer.at(layerID)) { ++layerID; j = 0; } @@ -695,13 +697,13 @@ { qint64 beginPos = device()->pos(); - if(!device()->seek(beginPos + (_demo ? 12 : 16))) { + if (!device()->seek(beginPos + (_demo ? 12 : 16))) { return false; } QMultiMap< quint8, QMultiMap< qint16, QMultiMap > > tilesByDst; - foreach(const Tile &tile, tiles) { + for (const Tile &tile : tiles) { QMultiMap< qint16, QMultiMap > tilesByDstY = tilesByDst.value(tile.layerID); QMultiMap tilesByDstX = tilesByDstY.value(tile.dstY); tilesByDstX.insert(tile.dstX, tile); @@ -712,31 +714,31 @@ quint32 pos = 0; qint16 currentLayer = -1; QMapIterator > > itLayer(tilesByDst); - while(itLayer.hasNext()) { + while (itLayer.hasNext()) { itLayer.next(); quint8 layerID = itLayer.key(); const QMultiMap > &tilesByDstY = itLayer.value(); quint16 line = 0; QMapIterator< qint16, QMultiMap > itDstY(tilesByDstY); - while(itDstY.hasNext()) { + while (itDstY.hasNext()) { itDstY.next(); const QMultiMap &tilesByDstX = itDstY.value(); - foreach(qint16 dstX, tilesByDstX.keys()) { + for (qint16 dstX : tilesByDstX.keys()) { int count = tilesByDstX.count(dstX); - if(pos > 65535) { + if (pos > 65535) { qWarning() << "BackgroundTilesIOPS::writeData Tile pos overflow" << pos; return false; } - if(count > 65535 || count < 0) { + if (count > 65535 || count < 0) { qWarning() << "BackgroundTilesIOPS::writeData Tile count overflow" << count; return false; } // Separation between layers - if(currentLayer >= 0 && layerID != currentLayer) { + if (currentLayer >= 0 && layerID != currentLayer) { quint16 flag = 0x7FFF; device()->write((char *)&flag, 2); // Infos about the next tile @@ -752,7 +754,7 @@ } // Separation between Y (only when several lines) - if(tilesByDstY.keys().size() > 1) { + if (tilesByDstY.keys().size() > 1) { quint16 flag = 0x7FFE; device()->write((char *)&flag, 2); device()->write((char *)&line, 2); @@ -780,21 +782,21 @@ qint16 dstY; bool firstTurn = true; - foreach(const Tile &tile, tiles.tiles(0, true)) { + for (const Tile &tile : tiles.tiles(0, true)) { writeTileBase(tile); - if(firstTurn || tile.dstY != dstY) { + if (firstTurn || tile.dstY != dstY) { tiles2.append(tile); dstY = tile.dstY; firstTurn = false; } } - if(!_demo) { + if (!_demo) { // Collect tiles2 for layers 2 and 3 firstTurn = true; - foreach(const Tile &tile, tilesLayers2And3) { - if(firstTurn || tile.dstY != dstY) { + for (const Tile &tile : qAsConst(tilesLayers2And3)) { + if (firstTurn || tile.dstY != dstY) { tiles2.append(tile); dstY = tile.dstY; firstTurn = false; @@ -804,34 +806,34 @@ positions[1] = device()->pos(); - foreach(const Tile &tile, tiles2) { + for (const Tile &tile : tiles2) { writeTileTex(tile); } positions[2] = device()->pos(); - foreach(const Tile &tile, tiles.tiles(1, true)) { + for (const Tile &tile : tiles.tiles(1, true)) { writeTileBase(tile); writeTileTex(tile); writeTileID(tile); writeTileParam(tile); } - if(!_demo) { + if (!_demo) { positions[3] = device()->pos(); - foreach(const Tile &tile, tilesLayers2And3) { + for (const Tile &tile : qAsConst(tilesLayers2And3)) { writeTileBase(tile); writeTileParam(tile); } } // Write pointers to sections - if(!device()->seek(beginPos)) { + if (!device()->seek(beginPos)) { return false; } - foreach(quint32 pos, positions) { + for (quint32 pos : qAsConst(positions)) { device()->write((char *)&pos, 4); } diff -Nru makoureactor-1.7.2/core/field/BsxFile.cpp makoureactor-1.8.0/core/field/BsxFile.cpp --- makoureactor-1.7.2/core/field/BsxFile.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/BsxFile.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -159,7 +159,7 @@ QList rects; - foreach (const BsxTextureHeader &h, headers) { + for (const BsxTextureHeader &h : qAsConst(headers)) { rects.append(QRect(h.vramX, h.vramY, h.width, h.height)); } @@ -289,7 +289,7 @@ bool BsxFile::readMesh(const QList &partsHeaders, FieldModelSkeleton &skeleton) const { - foreach (const FieldModelPartPSHeader &header, partsHeaders) { + for (const FieldModelPartPSHeader &header : partsHeaders) { FieldModelPart *part = new FieldModelPart(); if (!readPart(header, part)) { @@ -516,7 +516,7 @@ for (quint8 j = 0; j < 4; ++j) { quint8 vertexIndex = monochromeTexturedQuad.vertexIndex[j]; quint8 texCoordIndex = monochromeTexturedQuad.texCoordId[j]; - if(vertexIndex < vertices.size() && texCoordIndex < texCoords.size()) { + if (vertexIndex < vertices.size() && texCoordIndex < texCoords.size()) { polyVertices.append(vertices.at(vertexIndex)); polyTexCoords.append(texCoords.at(texCoordIndex)); } else { @@ -678,7 +678,7 @@ for (quint8 j = 0; j < 4; ++j) { quint8 vertexIndex = colorQuad.vertexIndex[j]; - if(vertexIndex < vertices.size()) { + if (vertexIndex < vertices.size()) { polyVertices.append(vertices.at(vertexIndex)); const ColorRGBA &color = colorQuad.color[j]; polyColors.append(qRgb(color.red, color.green, color.blue)); @@ -719,7 +719,7 @@ bool BsxFile::readAnimations(const QList &animationHeaders, QList &animations) const { - foreach (const FieldModelAnimationPSHeader &header, animationHeaders) { + for (const FieldModelAnimationPSHeader &header : animationHeaders) { FieldModelAnimation animation; if (!readAnimation(header, animation)) { @@ -922,7 +922,7 @@ { qint64 offsetTextures = _offsetModels + _offsetTextures; - foreach (const BsxTextureHeader &header, headers) { + for (const BsxTextureHeader &header : headers) { if (device()->pos() != offsetTextures + header.offsetData) { qWarning() << "BsxFile::readTexturesData error pos" << _offsetModels << _offsetTextures << header.offsetData << device()->pos(); return false; diff -Nru makoureactor-1.7.2/core/field/CaFile.cpp makoureactor-1.8.0/core/field/CaFile.cpp --- makoureactor-1.7.2/core/field/CaFile.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/CaFile.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -23,6 +23,26 @@ { } +void CaFile::initEmpty() +{ + cameras.clear(); + Camera ca = Camera(); + ca.camera_axis[0].x = 4094; + ca.camera_axis[0].y = -101; + ca.camera_axis[0].z = -1; + ca.camera_axis[1].x = -59; + ca.camera_axis[1].y = -2390; + ca.camera_axis[1].z = -3327; + ca.camera_axis[2].x = 81; + ca.camera_axis[2].y = 3325; + ca.camera_axis[2].z = -2391; + ca.camera_position[0] = -42; + ca.camera_position[1] = -255; + ca.camera_position[2] = 1476; + ca.camera_zoom = 525; + cameras.append(ca); +} + bool CaFile::open() { return open(field()->sectionData(Field::Camera)); @@ -34,14 +54,14 @@ int caSize = data.size(); bool isPC; - if(sizeof(Camera) != 40) { + if (sizeof(Camera) != 40) { qWarning() << "sizeof ca struct error" << sizeof(Camera); return false; } - if(caSize == 40 || ((caSize - 38) > 0 && (caSize - 38) % 18 == 0)) { + if (caSize == 40 || ((caSize - 38) > 0 && (caSize - 38) % 18 == 0)) { isPC = false; - } else if(caSize == 38 || caSize % 38 == 0) { + } else if (caSize == 38 || caSize % 38 == 0) { isPC = true; } else { qWarning() << "invalid ca size" << caSize; @@ -56,20 +76,20 @@ memcpy(&camera, constData, caSize != 40 ? 38 : 40); cameras.append(camera); - if(caSize > 40) { + if (caSize > 40) { /* The structure can be partially filled * In that case, values of the first camera * are implicitly used to complete. */ quint32 caCount; - if(isPC) { + if (isPC) { caCount = caSize/38; - for(quint32 i=1 ; iisPS() && camId > 0) { + if (field()->isPS() && camId > 0) { ca.append((char *)&camera, 18); } else { camera.camera_axis2z = camera.camera_axis[2].z; @@ -136,7 +156,7 @@ bool CaFile::removeCamera(int camID) { - if(cameras.size() > 1) { + if (cameras.size() > 1) { cameras.removeAt(camID); setModified(true); return true; diff -Nru makoureactor-1.7.2/core/field/CaFile.h makoureactor-1.8.0/core/field/CaFile.h --- makoureactor-1.7.2/core/field/CaFile.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/CaFile.h 2020-08-08 18:46:56.000000000 +0000 @@ -38,6 +38,7 @@ { public: explicit CaFile(Field *field); + void initEmpty(); bool open(); bool open(const QByteArray &data); QByteArray save() const; diff -Nru makoureactor-1.7.2/core/field/CharArchive.cpp makoureactor-1.8.0/core/field/CharArchive.cpp --- makoureactor-1.7.2/core/field/CharArchive.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/CharArchive.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -1,15 +1,29 @@ #include "CharArchive.h" +#include "AFile.h" #include "Data.h" -CharArchive::CharArchive() +CharArchive::CharArchive() : + _io(new Lgp()), _delete(true) +{ +} + +CharArchive::CharArchive(Lgp *io) : + _io(io), _delete(false) { } CharArchive::CharArchive(const QString &filename) : - _io(filename) + _io(new Lgp(filename)), _delete(true) { } +CharArchive::~CharArchive() +{ + if (_delete) { + delete _io; + } +} + CharArchive *CharArchive::_instance = 0; CharArchive *CharArchive::instance() @@ -25,8 +39,8 @@ void CharArchive::close() { - _io.clear(); - _io.close(); + _io->clear(); + _io->close(); _animBoneCount.clear(); } @@ -34,8 +48,8 @@ { QStringList files; - foreach(const QString &file, _io.fileList()) { - if(file.endsWith(".hrc", Qt::CaseInsensitive)) { + for (const QString &file : _io->fileList()) { + if (file.endsWith(".hrc", Qt::CaseInsensitive)) { files.append(file.toUpper()); } } @@ -45,14 +59,14 @@ QStringList CharArchive::aFiles(int boneCount) { - if(boneCount >= 0 && openAnimBoneCount()) { + if (boneCount >= 0 && openAnimBoneCount()) { return _animBoneCount.values(boneCount); } QStringList files; - foreach(const QString &file, _io.fileList()) { - if(file.endsWith(".a", Qt::CaseInsensitive)) { + for (const QString &file : _io->fileList()) { + if (file.endsWith(".a", Qt::CaseInsensitive)) { files.append(file.left(file.size()-2).toUpper()); } } @@ -62,7 +76,7 @@ QIODevice *CharArchive::fileIO(const QString &filename) { - return _io.file(filename.toLower()); + return _io->file(filename.toLower()); } bool CharArchive::openAnimBoneCount() @@ -74,21 +88,22 @@ _animBoneCount.clear(); - LgpIterator it = _io.iterator(); - while(it.hasNext()) { + LgpIterator it = _io->iterator(); + while (it.hasNext()) { it.next(); const QString &fileName = it.fileName(); - if(fileName.endsWith(".a", Qt::CaseInsensitive)) { - QCoreApplication::processEvents(); + if (fileName.endsWith(".a", Qt::CaseInsensitive)) { QIODevice *aFile = it.file(); - if(aFile && aFile->open(QIODevice::ReadOnly)) { - quint32 boneCount; - if(!aFile->seek(8) || - aFile->read((char *)&boneCount, 4) != 4) { + if (aFile && aFile->open(QIODevice::ReadOnly)) { + AFile a(aFile); + AHeader header; + + if (!a.readHeader(header)) { qWarning() << "CharArchive::openAnimBoneCount" << "animation error" << fileName; continue; } - _animBoneCount.insert(boneCount, fileName.left(fileName.size()-2).toUpper()); + + _animBoneCount.insert(header.boneCount, fileName.left(fileName.size()-2).toUpper()); } else { return false; } diff -Nru makoureactor-1.7.2/core/field/CharArchive.h makoureactor-1.8.0/core/field/CharArchive.h --- makoureactor-1.7.2/core/field/CharArchive.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/CharArchive.h 2020-08-08 18:46:56.000000000 +0000 @@ -7,22 +7,24 @@ { public: CharArchive(); + explicit CharArchive(Lgp *io); explicit CharArchive(const QString &filename); + virtual ~CharArchive(); static CharArchive *instance(); inline bool isOpen() const { - return _io.isOpen(); + return _io->isOpen(); } inline bool open() { - return _io.open(); + return _io->open(); } void close(); inline QString filename() const { - return _io.fileName(); + return _io->fileName(); } inline void setFilename(const QString &filename) { - _io.setFileName(filename); + _io->setFileName(filename); } QStringList hrcFiles() const; QStringList aFiles(int boneCount = -1); @@ -30,8 +32,9 @@ private: bool openAnimBoneCount(); - Lgp _io; + Lgp *_io; QMultiHash _animBoneCount; + bool _delete; static CharArchive *_instance; }; diff -Nru makoureactor-1.7.2/core/field/EncounterFile.cpp makoureactor-1.8.0/core/field/EncounterFile.cpp --- makoureactor-1.7.2/core/field/EncounterFile.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/EncounterFile.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -23,6 +23,12 @@ { } +void EncounterFile::initEmpty() +{ + tables[0] = EncounterTable(); + tables[1] = EncounterTable(); +} + bool EncounterFile::open() { return open(field()->sectionData(Field::Encounter)); @@ -30,12 +36,12 @@ bool EncounterFile::open(const QByteArray &data) { - if(sizeof(EncounterTable) != 24) { + if (sizeof(EncounterTable) != 24) { qWarning() << "Encounter invalid struct size" << sizeof(EncounterTable); Q_ASSERT(false); } - if(data.size() != 48) { + if (data.size() != 48) { qWarning() << "Encounter invalid data size" << data.size(); return false; } diff -Nru makoureactor-1.7.2/core/field/EncounterFile.h makoureactor-1.8.0/core/field/EncounterFile.h --- makoureactor-1.7.2/core/field/EncounterFile.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/EncounterFile.h 2020-08-08 18:46:56.000000000 +0000 @@ -40,6 +40,7 @@ }; explicit EncounterFile(Field *field); + void initEmpty(); bool open(); bool open(const QByteArray &data); QByteArray save() const; diff -Nru makoureactor-1.7.2/core/field/FieldArchive.cpp makoureactor-1.8.0/core/field/FieldArchive.cpp --- makoureactor-1.7.2/core/field/FieldArchive.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldArchive.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -19,35 +19,56 @@ #include "FieldPS.h" #include "FieldPC.h" #include "Data.h" +#include "core/PsfFile.h" +#include "Parameters.h" FieldArchiveIterator::FieldArchiveIterator(const FieldArchive &archive) : - QListIterator(archive.fileList) + QMapIterator(archive.fileList), mapList(archive.fileList) { } +bool FieldArchiveIterator::seek(int mapId) +{ + toFront(); + + if (mapId < 0) { + return true; + } + + Field *f = mapList.value(mapId); + if (nullptr != f && findNext(f)) { + previous(); + return true; + } + + toFront(); + + return false; +} + Field *FieldArchiveIterator::next(bool open, bool dontOptimize) { - return openField(QListIterator::next(), open, dontOptimize); + return openField(QMapIterator::next().value(), open, dontOptimize); } Field *FieldArchiveIterator::peekNext(bool open, bool dontOptimize) const { - return openField(QListIterator::peekNext(), open, dontOptimize); + return openField(QMapIterator::peekNext().value(), open, dontOptimize); } Field *FieldArchiveIterator::peekPrevious(bool open, bool dontOptimize) const { - return openField(QListIterator::peekPrevious(), open, dontOptimize); + return openField(QMapIterator::peekPrevious().value(), open, dontOptimize); } Field *FieldArchiveIterator::previous(bool open, bool dontOptimize) { - return openField(QListIterator::previous(), open, dontOptimize); + return openField(QMapIterator::previous().value(), open, dontOptimize); } Field *FieldArchiveIterator::openField(Field *field, bool open, bool dontOptimize) { - if(field != NULL && open && !field->isOpen()) { + if (field != nullptr && open && !field->isOpen()) { field->open(dontOptimize); } return field; @@ -69,28 +90,28 @@ FieldArchive::~FieldArchive() { qDeleteAll(fileList); - if(_io) delete _io; + if (_io) delete _io; } FieldArchiveIO::ErrorCode FieldArchive::open() { - if(!_io) return FieldArchiveIO::Invalid; + if (!_io) return FieldArchiveIO::Invalid; // qDebug() << "FieldArchive::open()"; clear(); FieldArchiveIO::ErrorCode error = _io->open(observer()); - if(error != FieldArchiveIO::Ok) { + if (error != FieldArchiveIO::Ok) { return error; } - if(fileList.isEmpty()) return FieldArchiveIO::FieldNotFound; + if (fileList.isEmpty()) return FieldArchiveIO::FieldNotFound; - if(Data::field_names.isEmpty()) { + if (Data::maplist().isEmpty()) { Data::openMaplist(_io->isPC()); } int fieldID=0; - foreach(Field *f, fileList) { + for (Field *f : qAsConst(fileList)) { updateFieldLists(f, fieldID); ++fieldID; } @@ -102,10 +123,10 @@ FieldArchiveIO::ErrorCode FieldArchive::save(const QString &path) { - if(!_io) return FieldArchiveIO::Invalid; + if (!_io) return FieldArchiveIO::Invalid; FieldArchiveIO::ErrorCode error = _io->save(path, observer()); - if(error == FieldArchiveIO::Ok) { + if (error == FieldArchiveIO::Ok) { // Clear "isModified" state setSaved(); } @@ -114,7 +135,7 @@ void FieldArchive::close() { - if(_io) _io->close(); + if (_io) _io->close(); } void FieldArchive::clear() @@ -122,8 +143,7 @@ qDeleteAll(fileList); fileList.clear(); fieldsSortByName.clear(); - fieldsSortByMapId.clear(); - Data::field_names.clear(); + Data::setMaplist(QStringList()); } FieldArchiveIO *FieldArchive::io() const @@ -138,7 +158,7 @@ bool FieldArchive::openField(Field *field, bool dontOptimize) { - if(!field->isOpen()) { + if (!field->isOpen()) { return field->open(dontOptimize); } return true; @@ -149,16 +169,16 @@ return fieldsSortByName.value(name.toLower(), -1); } -const Field *FieldArchive::field(quint32 id) const +const Field *FieldArchive::field(quint32 mapId) const { - return fileList.value(id, NULL); + return fileList.value(mapId, nullptr); } -Field *FieldArchive::field(quint32 id, bool open, bool dontOptimize) +Field *FieldArchive::field(quint32 mapId, bool open, bool dontOptimize) { - Field *field = fileList.value(id, NULL); - if(field!=NULL && open && !openField(field, dontOptimize)) { - return NULL; + Field *field = fileList.value(mapId, nullptr); + if (field != nullptr && open && !openField(field, dontOptimize)) { + return nullptr; } return field; } @@ -173,74 +193,83 @@ return field(indexOfField(name), open, dontOptimize); } -void FieldArchive::updateFieldLists(Field *field, int fieldID) +void FieldArchive::updateFieldLists(Field *field, int mapId) { - const QString &name = field->name(); - - int index = Data::field_names.indexOf(name); - QString mapId = index != -1 ? - QString("%1").arg(index, 3) : - "~"; - - fieldsSortByName.insert(name.toLower(), fieldID); - fieldsSortByMapId.insert(mapId, fieldID); + fieldsSortByName.insert(field->name().toLower(), mapId); } -FieldArchiveIO::ErrorCode FieldArchive::addField(Field *field, - const QString &fileName, - int &fieldId) +void FieldArchive::addNewField(Field *field, int &mapID) { - fieldId = fileList.size(); - /* FieldArchiveIO::ErrorCode err = _io->addField(fileName, field->name()); - if(err != FieldArchiveIO::Ok) { - return err; - }*/ - appendField(field); - // FIXME: choose another name? Multiple fields with the same name - Data::field_names.append(field->name()); - updateFieldLists(field, fieldId); - return FieldArchiveIO::Ok; + mapID = appendField(field); + Data::addMap(field->name()); + updateFieldLists(field, mapID); } -void FieldArchive::appendField(Field *field) +void FieldArchive::delField(int mapId) { - fileList.append(field); + Field *field = fileList.value(mapId); + + if (nullptr == field) { + return; + } + + QStringList maplist = Data::maplist(); + + for (int i = 0; i < maplist.size(); ++i) { + if (maplist.at(i) == field->name()) { + Data::setMap(i, ""); + } + } + + fileList.insert(mapId, nullptr); + delete field; } -void FieldArchive::removeField(quint32 id) +int FieldArchive::appendField(Field *field) { - fileList.removeAt(id); + int mapId = Data::maplist().indexOf(field->name()); + if (mapId < 0) { + mapId = 1200 + (fileList.isEmpty() ? 0 : fileList.lastKey() + 1); + } + fileList.insert(mapId, field); + return mapId; } bool FieldArchive::isAllOpened() const { - foreach(Field *f, fileList) { - if(!f->isOpen()) return false; + for (Field *f : fileList) { + if (!f->isOpen()) { + return false; + } } + return true; } bool FieldArchive::isModified() const { - foreach(Field *f, fileList) { - if(f->isModified()) return true; + for (Field *f : fileList) { + if (f->isModified()) { + return true; + } } + return false; } QList FieldArchive::searchAllVars(QMap > &fieldNames) { - Q_UNUSED(fieldNames) QList vars; - int size = fileList.size(); + FieldArchiveIterator it(*this); - for(int i=0 ; ifield(i); - if(field != NULL) { + while (it.hasNext()) { + Field *field = it.next(); + + if (field != nullptr) { QList fieldVars; field->scriptsAndTexts()->searchAllVars(fieldVars); - foreach (const FF7Var &fieldVar, fieldVars) { + + for (const FF7Var &fieldVar : qAsConst(fieldVars)) { QSet names = fieldNames.value(fieldVar); names.insert(field->scriptsAndTexts()->author()); fieldNames.insert(fieldVar, names); @@ -262,25 +291,28 @@ void FieldArchive::validateAsk() { - foreach(int i, fieldsSortByMapId) { - Field *f = field(i, true); - QString name = Data::field_names.value(fieldsSortByMapId.key(i).toInt()); - if(f == NULL) { - qWarning() << "FieldArchive::printAkaos: cannot open field" << i << name; + FieldArchiveIterator it(*this); + + while (it.hasNext()) { + Field *f = it.next(); + + if (f == nullptr) { + qWarning() << "FieldArchive::printAkaos: cannot open field" << it.mapId(); continue; } + QString name = f->name(); + Section1File *scriptsAndTexts = f->scriptsAndTexts(); - if(scriptsAndTexts->isOpen()) { - //qWarning() << f->name(); + if (scriptsAndTexts->isOpen()) { int grpScriptID = 0; - foreach(GrpScript *grp, scriptsAndTexts->grpScripts()) { + for (GrpScript *grp : scriptsAndTexts->grpScripts()) { int scriptID = 0; - foreach(Script *script, grp->scripts()) { + for (Script *script : grp->scripts()) { int opcodeID = 0; - foreach(Opcode *opcode, script->opcodes()) { - if(opcode->id() == Opcode::ASK) { + for (Opcode *opcode : script->opcodes()) { + if (opcode->id() == Opcode::ASK) { OpcodeASK *opcodeASK = static_cast(opcode); quint8 textID = opcodeASK->textID, firstLine = opcodeASK->firstLine, @@ -290,7 +322,7 @@ if (!text.isEmpty()) { int lineNum = 0, autoFirstLine = -1, autoLastLine = -1; bool hasChoice = false; - foreach (const QString &line, text.split('\n')) { + for (const QString &line : text.split('\n')) { if (line.startsWith("{CHOICE}")) { if (!hasChoice) { if (autoFirstLine == -1) { @@ -315,13 +347,13 @@ if (autoFirstLine == -1) { qWarning() << QString("%1 > %2 > %3 > %4: No {CHOICE} here (textID: %9)") - .arg(f->name(), grp->name(), grp->scriptName(scriptID)) + .arg(name, grp->name(), grp->scriptName(scriptID)) .arg(opcodeID + 1) .arg(textID).toLatin1().data(); } else if (autoFirstLine != firstLine || autoLastLine != lastLine) { qWarning() << QString("%1 > %2 > %3 > %4: %5 should be %6, %7 should be %8 (textID: %9)") - .arg(f->name(), grp->name(), grp->scriptName(scriptID)) + .arg(name, grp->name(), grp->scriptName(scriptID)) .arg(opcodeID + 1) .arg(firstLine).arg(autoFirstLine) .arg(lastLine).arg(autoLastLine) @@ -345,30 +377,33 @@ void FieldArchive::validateOneLineSize() { TextPreview tp; // Init textpreview to use autodim algo + FieldArchiveIterator it(*this); - foreach(int i, fieldsSortByMapId) { - Field *f = field(i, true); - QString name = Data::field_names.value(fieldsSortByMapId.key(i).toInt()); - if(f == NULL) { - qWarning() << "FieldArchive::printAkaos: cannot open field" << i << name; + while (it.hasNext()) { + Field *f = it.next(); + + if (f == nullptr) { + qWarning() << "FieldArchive::printAkaos: cannot open field" << it.mapId(); continue; } + QString name = f->name(); + Section1File *scriptsAndTexts = f->scriptsAndTexts(); - if(scriptsAndTexts->isOpen()) { + if (scriptsAndTexts->isOpen()) { //qWarning() << f->name(); int grpScriptID = 0; - foreach(GrpScript *grp, scriptsAndTexts->grpScripts()) { + for (GrpScript *grp : scriptsAndTexts->grpScripts()) { int scriptID = 0; - foreach(Script *script, grp->scripts()) { + for (Script *script : grp->scripts()) { int opcodeID = 0; OpcodeWindow *opcodeWindow = 0; - foreach(Opcode *opcode, script->opcodes()) { - if(opcode->id() == Opcode::WSIZW + for (Opcode *opcode : script->opcodes()) { + if (opcode->id() == Opcode::WSIZW || opcode->id() == Opcode::WINDOW) { opcodeWindow = static_cast(opcode); - } else if(opcode->getTextID() >= 0 && opcodeWindow) { + } else if (opcode->getTextID() >= 0 && opcodeWindow) { FF7Window window; opcodeWindow->getWindow(window); if (opcode->getTextID() < scriptsAndTexts->textCount()) { @@ -395,22 +430,23 @@ { QFile deb(filename); deb.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); + FieldArchiveIterator it(*this); - foreach(int i, fieldsSortByMapId) { - Field *f = field(i, true); - if(f == NULL) { - qWarning() << "FieldArchive::printAkaos: cannot open field" << i; + while (it.hasNext()) { + Field *f = it.next(); + if (f == nullptr) { + qWarning() << "FieldArchive::printAkaos: cannot open field" << it.mapId(); continue; } QString name = f->inf()->mapName(); TutFileStandard *tutosAndSounds = f->tutosAndSounds(); - if(!tutosAndSounds->isOpen()) { + if (!tutosAndSounds->isOpen()) { qWarning() << "FieldArchive::printAkaos: cannot open tutos and sounds" << name; } - for(int akaoID=0; akaoID < tutosAndSounds->size(); ++akaoID) { - if(tutosAndSounds->isTut(akaoID)) { + for (int akaoID=0; akaoID < tutosAndSounds->size(); ++akaoID) { + if (tutosAndSounds->isTut(akaoID)) { deb.write(QString("%1 > tuto %2\n") .arg(name) .arg(akaoID) @@ -430,11 +466,12 @@ { QFile deb(filename); deb.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); + FieldArchiveIterator it(*this); - foreach(int i, fieldsSortByMapId) { - Field *f = field(i, true); - if(f == NULL) { - qWarning() << "FieldArchive::printModelLoaders: cannot open field" << i; + while (it.hasNext()) { + Field *f = it.next(); + if (f == nullptr) { + qWarning() << "FieldArchive::printModelLoaders: cannot open field" << it.mapId(); continue; } if (!f->inf()->isOpen()) { @@ -444,7 +481,7 @@ QString name = f->inf()->mapName(); FieldModelLoader *modelLoader = f->fieldModelLoader(); - if(!modelLoader->isOpen()) { + if (!modelLoader->isOpen()) { qWarning() << "FieldArchive::printModelLoaders: cannot open tutos and sounds" << name; continue; } @@ -458,11 +495,11 @@ if (f->isPC()) { FieldModelLoaderPC *modelLoaderPC = static_cast(modelLoader); scale = modelLoaderPC->scale(modelId); - colors = modelLoaderPC->lightColors(modelId); + // colors = modelLoaderPC->lightColors(modelId); } else { FieldModelFilePS *fieldModelPS = static_cast(fieldModel); scale = fieldModelPS->scale(); - colors = fieldModelPS->lightColors(); + // colors = fieldModelPS->lightColors(); boneCount -= 1; if (boneCount <= 0) { boneCount = 1; @@ -476,7 +513,7 @@ .arg(modelLoader->unknown(modelId)) .toLatin1()); - /* foreach (const QRgb &color, colors) { + /* for (const QRgb &color : colors) { deb.write(QString("%1, ") .arg(color).toLatin1()); } @@ -488,11 +525,11 @@ .toLatin1()); }*/ } - } else if(f->isPC()) { + } else if (f->isPC()) { FieldModelLoaderPC *modelLoaderPC = static_cast(modelLoader); int modelID = 0; - foreach(const QString &hrc, modelLoaderPC->HRCNames()) { + for (const QString &hrc : modelLoaderPC->HRCNames()) { deb.write(QString("%1 > model %2: %3\n") .arg(name) .arg(modelID) @@ -500,7 +537,7 @@ .toLatin1()); int animID = 0; - foreach(const QString &a, modelLoaderPC->ANames(modelID)) { + for (const QString &a : modelLoaderPC->ANames(modelID)) { deb.write(QString("\tanim %1: %2\n") .arg(animID) .arg(a.toLower().left(a.lastIndexOf('.'))) @@ -514,28 +551,71 @@ } } -void FieldArchive::printTexts(const QString &filename) +void FieldArchive::printTexts(const QString &filename, bool usedTexts) { QFile deb(filename); deb.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); + FieldArchiveIterator it(*this); - foreach(int i, fieldsSortByMapId) { - Field *f = field(i, true); - if(f == NULL) { - qWarning() << "FieldArchive::printTexts: cannot open field" << i; + while (it.hasNext()) { + Field *f = it.next(); + if (f == nullptr) { + qWarning() << "FieldArchive::printTexts: cannot open field" << it.mapId(); continue; } Section1File *scriptsAndTexts = f->scriptsAndTexts(); - if(scriptsAndTexts->isOpen()) { + if (scriptsAndTexts->isOpen()) { qWarning() << f->inf()->mapName(); + QSet listUsedTexts = usedTexts ? scriptsAndTexts->listUsedTexts() : QSet(); - int textID = 0; - foreach(const FF7Text &text, scriptsAndTexts->texts()) { - deb.write(QString("%1 > %2:\n%3\n\n") - .arg(f->inf()->mapName()) - .arg(textID) - .arg(text.text(false)).toUtf8()); + deb.write(QString("\n=== %1 ===\n\n") + .arg(f->inf()->mapName()).toUtf8()); + + quint8 textID = 0; + for (const FF7Text &text : scriptsAndTexts->texts()) { + if ((!usedTexts || listUsedTexts.contains(textID)) && !text.data().isEmpty()) { + deb.write(QString("%1\n\n") + .arg(text.text(false)).toUtf8()); + } + textID++; + } + } + } +} + +void FieldArchive::printTextsDir(const QString &dirname, bool usedTexts) +{ + QDir dir(dirname); + + if (!dir.exists()) { + dir.mkpath(dirname); + } + + FieldArchiveIterator it(*this); + + while (it.hasNext()) { + Field *f = it.next(); + + if (f == nullptr) { + qWarning() << "FieldArchive::printTexts: cannot open field" << it.mapId(); + continue; + } + + QFile deb(dir.filePath(f->name() + ".txt")); + deb.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); + + Section1File *scriptsAndTexts = f->scriptsAndTexts(); + if (scriptsAndTexts->isOpen()) { + qWarning() << f->inf()->mapName(); + QSet listUsedTexts = usedTexts ? scriptsAndTexts->listUsedTexts() : QSet(); + + quint8 textID = 0; + for (const FF7Text &text : scriptsAndTexts->texts()) { + if (!usedTexts || listUsedTexts.contains(textID)) { + deb.write(QString("%1\n\n") + .arg(text.text(false)).toUtf8()); + } textID++; } } @@ -558,19 +638,19 @@ FieldArchiveIterator it(*this); while (it.hasNext()) { Field *f1 = it.next(); - if(f1 == NULL) { + if (f1 == nullptr) { qWarning() << "FieldArchive::compareTexts: cannot open field"; continue; } Field *f2 = other->field(f1->name()); - if(f2 == NULL) { + if (f2 == nullptr) { qWarning() << "FieldArchive::compareTexts: cannot find field2" << f1->name(); continue; } Section1File *scriptsAndTexts1 = f1->scriptsAndTexts(), *scriptsAndTexts2 = f2->scriptsAndTexts(); - if(scriptsAndTexts1->isOpen() && scriptsAndTexts2->isOpen()) { + if (scriptsAndTexts1->isOpen() && scriptsAndTexts2->isOpen()) { qWarning() << f1->name(); if (scriptsAndTexts1->textCount() != scriptsAndTexts2->textCount()) { @@ -579,7 +659,7 @@ } int textID = 0; - foreach(const FF7Text &text1, scriptsAndTexts1->texts()) { + for (const FF7Text &text1 : scriptsAndTexts1->texts()) { const FF7Text &text2 = scriptsAndTexts2->text(textID); if (text1 != text2) { QStringList lines1 = text1.text(false).split("\n"), @@ -612,25 +692,27 @@ QFile deb(filename); deb.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); - foreach(int i, fieldsSortByMapId) { - Field *f = field(i, true); - if(f == NULL) { - qWarning() << "FieldArchive::printAkaos: cannot open field" << i; + FieldArchiveIterator it(*this); + + while (it.hasNext()) { + Field *f = it.next(); + if (f == nullptr) { + qWarning() << "FieldArchive::printAkaos: cannot open field" << it.mapId(); continue; } Section1File *scriptsAndTexts = f->scriptsAndTexts(); - if(scriptsAndTexts->isOpen()) { + if (scriptsAndTexts->isOpen()) { qWarning() << f->inf()->mapName(); int grpScriptID = 0; - foreach(GrpScript *grp, scriptsAndTexts->grpScripts()) { + for (GrpScript *grp : scriptsAndTexts->grpScripts()) { int scriptID = 0; - foreach(Script *script, grp->scripts()) { + for (Script *script : grp->scripts()) { int opcodeID = 0; - foreach(Opcode *opcode, script->opcodes()) { + for (Opcode *opcode : script->opcodes()) { FF7Window win; - /* if(opcode->getWindow(win)) { + /* if (opcode->getWindow(win)) { deb.write(QString("%1 > %2 > %3: %4 %5\n") .arg(f->name(), grp->name()) .arg(scriptID) @@ -654,19 +736,25 @@ void FieldArchive::printScriptsDirs(const QString &filename) { QDir dir(filename); - if(!dir.exists()) { + if (!dir.exists()) { dir.mkdir("."); } - foreach(int i, fieldsSortByMapId) { - Field *f = field(i, true); - if(f == NULL) { - qWarning() << "FieldArchive::printAkaos: cannot open field" << i; + FieldArchiveIterator it(*this); + + while (it.hasNext()) { + Field *f = it.next(); + + if (f == nullptr) { + qWarning() << "FieldArchive::printScriptsDirs: cannot open field" << it.mapId(); + continue; + } + if (!f->name().startsWith("del")) { continue; } Section1File *scriptsAndTexts = f->scriptsAndTexts(); - if(scriptsAndTexts->isOpen()) { + if (scriptsAndTexts->isOpen()) { qWarning() << f->inf()->mapName(); QString dirname = f->inf()->mapName(); @@ -674,7 +762,7 @@ dir.cd(dirname); int grpScriptID = 0; - foreach(GrpScript *grp, scriptsAndTexts->grpScripts()) { + for (GrpScript *grp : scriptsAndTexts->grpScripts()) { dirname = QString("%1-%2") .arg(grpScriptID, 2, 10, QChar('0')) @@ -683,7 +771,7 @@ dir.cd(dirname); int scriptID = 0; - foreach(Script *script, grp->scripts()) { + for (Script *script : grp->scripts()) { QFile deb(dir.filePath(QString("%1-script").arg(scriptID, 2, 10, QChar('0')))); if (!deb.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { @@ -692,9 +780,9 @@ } int opcodeID = 0; - foreach(Opcode *opcode, script->opcodes()) { + for (Opcode *opcode : script->opcodes()) { // FF7Window win; - /* if(opcode->getWindow(win)) { + /* if (opcode->getWindow(win)) { deb.write(QString("%1 > %2 > %3: %4 %5\n") .arg(f->name(), grp->name()) .arg(scriptID) @@ -706,6 +794,7 @@ opcodeID++; } scriptID++; + deb.close(); } dir.cdUp(); grpScriptID++; @@ -719,27 +808,28 @@ void FieldArchive::diffScripts() { FieldArchivePC original("C:/Program Files/Square Soft, Inc/Final Fantasy VII/data/field/fflevel - original.lgp", FieldArchiveIO::Lgp); - if(original.open() != FieldArchiveIO::Ok) { + if (original.open() != FieldArchiveIO::Ok) { qWarning() << "error opening pc lgp"; return; } QSet screens; + FieldArchiveIterator it(*this); - foreach(int i, fieldsSortByMapId) { - Field *field = this->field(i, true); + while (it.hasNext()) { + Field *field = it.next(); Field *fieldOriginal = original.field(original.indexOfField(field->name())); - if(fieldOriginal == NULL) { + if (fieldOriginal == nullptr) { qWarning() << "ALERT field not found" << field->name(); break; } - if(field != NULL) { + if (field != nullptr) { Section1File *scriptsAndTexts = field->scriptsAndTexts(); Section1File *scriptsAndTextsOriginal = fieldOriginal->scriptsAndTexts(); - if(scriptsAndTexts->isOpen() && scriptsAndTextsOriginal->isOpen()) { + if (scriptsAndTexts->isOpen() && scriptsAndTextsOriginal->isOpen()) { qWarning() << field->name(); - if(scriptsAndTexts->grpScriptCount() < scriptsAndTextsOriginal->grpScriptCount()) { + if (scriptsAndTexts->grpScriptCount() < scriptsAndTextsOriginal->grpScriptCount()) { qWarning() << "ALERT much grpscript wow"; break; } @@ -748,37 +838,37 @@ deb.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); int grpScriptID = 0, scriptID; - foreach(GrpScript *group2, scriptsAndTextsOriginal->grpScripts()) { + for (GrpScript *group2 : scriptsAndTextsOriginal->grpScripts()) { GrpScript *grp = scriptsAndTexts->grpScript(grpScriptID); - while(group2->name() != grp->name()) { + while (group2->name() != grp->name()) { grpScriptID++; - if(grpScriptID >= scriptsAndTexts->grpScriptCount()) { + if (grpScriptID >= scriptsAndTexts->grpScriptCount()) { qWarning() << "ALERT end grpScript reached"; goto next_group; } grp = scriptsAndTexts->grpScript(grpScriptID); } - if(grp->size() != group2->size()) { + if (grp->size() != group2->size()) { qWarning() << "ALERT wrong group size" << grp->size() << group2->size(); break; } scriptID = 0; - foreach(Script *script2, group2->scripts()) { + for (Script *script2 : group2->scripts()) { Script *script = grp->script(scriptID); int opcodeID = 0; - foreach(Opcode *opcode2, script2->opcodes()) { + for (Opcode *opcode2 : script2->opcodes()) { FF7Window win, win2; - if(opcode2->getWindow(win2)) { + if (opcode2->getWindow(win2)) { Opcode *opcode; do { - if(opcodeID >= script->size()) { + if (opcodeID >= script->size()) { qWarning() << "ALERT wrong script size"; goto next_script; } @@ -793,7 +883,7 @@ hasTinyDiffY = diffY >= minDiff && diffY <= maxDiff, hasLargeDiffX = diffX > 15,//maxDiff, hasLargeDiffY = diffY > 15;//maxDiff; - if(diffX > 0 || diffY > 0) { //(hasTinyDiffX && hasLargeDiffY) || (hasTinyDiffY && hasLargeDiffX)) { + if (diffX > 0 || diffY > 0) { //(hasTinyDiffX && hasLargeDiffY) || (hasTinyDiffY && hasLargeDiffX)) { deb.write(QString("%1 > %2 > %3 > %4: window %5 (retraduit: %6, %7) (original: %8, %9)\n") .arg(field->name()) .arg(grp->name()) @@ -814,7 +904,7 @@ next_group:; grpScriptID++; } - if(deb.size() == 0) { + if (deb.size() == 0) { deb.remove(); } qDebug() << screens.size() << "écrans"; @@ -823,71 +913,113 @@ } } -bool FieldArchive::printBackgroundTiles(Field *field, const QString &filename, bool uniformize) +bool FieldArchive::printBackgroundTiles(bool uniformize, bool fromUnusedPCSection) { - QFile f(filename); - if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - qWarning() << "FieldArchive::printBackgroundTiles" << f.errorString(); - return false; - } + FieldArchiveIterator it(*this); + QDir dir(QString("background-tiles-%1").arg(isPC() ? "pc" : "ps")); + dir.mkpath("."); - BackgroundFile *bgFile = field->background(); - if (!bgFile || !bgFile->isOpen()) { - qWarning() << "FieldArchive::printBackgroundTiles no bg for this field" << field->name(); - return false; - } + while (it.hasNext()) { + Field *field = it.next(); + if (!field || !field->isOpen()) { + continue; + } + + InfFile *inf = field->inf(); + if (!inf || !inf->isOpen()) { + continue; + } - BackgroundTiles tiles; - if (uniformize && field->isPS()) { // Convert PS to PC to have the same output whenever the source - BackgroundFilePS *bgFilePS = static_cast(bgFile); - PalettesPC palettesPC = ((PalettesPS *)&(bgFilePS->palettes()))->toPC(); - static_cast(bgFilePS->textures()) - ->toPC(bgFilePS->tiles(), tiles, palettesPC); - } else { - tiles = bgFile->tiles(); - } - - foreach (const Tile &tile, tiles.sortedTiles()) { - f.write(QString("tileID=%1, layer=%2, param=%3, state=%4\n") - .arg(tile.tileID) - .arg(tile.layerID) - .arg(tile.param) - .arg(tile.state).toUtf8()); - f.write(QString("srcX=%1, srcY=%2, textureID1=%3, textureID2=%4\n") - .arg(tile.srcX) - .arg(tile.srcY) - .arg(tile.textureID) - .arg(tile.textureID2).toUtf8()); - f.write(QString("dstX=%1, dstY=%2, dstZ=%3, size=%4\n") - .arg(tile.dstX) - .arg(tile.dstY) - .arg(tile.ID) - .arg(tile.size).toUtf8()); - f.write(QString("palID=%1, depth=%2, blending=%3, typeTrans=%4\n") - .arg(tile.paletteID) - .arg(tile.depth) - .arg(tile.blending) - .arg(tile.typeTrans).toUtf8()); - f.write(QString("dstZBig=%1\n") - .arg(tile.IDBig).toUtf8()); - f.write("\n"); + QFile f(dir.filePath("field-" + inf->mapName() + ".txt")); + if (!f.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + qWarning() << "FieldArchive::printBackgroundTiles" << f.errorString() << f.fileName(); + return false; + } + + BackgroundFile *bgFile = field->background(); + if (!bgFile || !bgFile->isOpen()) { + qWarning() << "FieldArchive::printBackgroundTiles no bg for this field" << field->name(); + continue; + } + + BackgroundTiles tiles; + if (fromUnusedPCSection) { + BackgroundTilesFile *tilesFile = field->tiles(); + tiles = tilesFile->tiles(); + } + else if (uniformize && field->isPS()) { // Convert PS to PC to have the same output whenever the source + BackgroundFilePS *bgFilePS = static_cast(bgFile); + PalettesPC palettesPC = ((PalettesPS *)&(bgFilePS->palettes()))->toPC(); + static_cast(bgFilePS->textures()) + ->toPC(bgFilePS->tiles(), tiles, palettesPC); + } else { + tiles = bgFile->tiles(); + } + + for (const Tile &tile : tiles.sortedTiles()) { + f.write(QString("tileID=%1, layer=%2, param=%3, state=%4\n") + .arg(tile.tileID) + .arg(tile.layerID) + .arg(tile.param) + .arg(tile.state).toUtf8()); + /* f.write(QString("srcX=%1, srcY=%2, textureID1=%3, textureID2=%4\n") + .arg(tile.srcX) + .arg(tile.srcY) + .arg(tile.textureID) + .arg(tile.textureID2).toUtf8()); */ + f.write(QString("dstX=%1, dstY=%2, dstZ=%3, size=%4\n") + .arg(tile.dstX) + .arg(tile.dstY) + .arg(tile.ID) + .arg(tile.size).toUtf8()); + f.write(QString("palID=%1, depth=%2, blending=%3, typeTrans=%4\n") + .arg(tile.paletteID) + .arg(tile.depth) + .arg(tile.blending) + .arg(tile.typeTrans).toUtf8()); + //f.write(QString("dstZBig=%1\n") + // .arg(tile.IDBig).toUtf8()); + f.write("\n"); + } } return true; } -void FieldArchive::searchBackgroundZ() +void FieldArchive::printBackgroundZ() { QMultiMap ids; FieldArchiveIterator it(*this); + + QDir dir(QString("background-z-%1").arg(isPC() ? "pc" : "ps")); + dir.mkpath("."); + QFile deb2("background-z.txt"); + deb2.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); + while (it.hasNext()) { Field *field = it.next(); + if (field && field->isOpen()) { BackgroundFile *bg = field->background(); + InfFile *inf = field->inf(); + if (bg->isOpen()) { bool function1 = false; - foreach (const Tile &tile, bg->tiles()) { + + //QFile deb(dir.filePath("%1-background-id.txt").arg(inf->mapName())); + //deb.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); + + for (const Tile &tile : bg->tiles()) { + + //deb.write(QString("%1\n").arg(tile.ID).toLatin1()); + + if (tile.layerID == 1) + ids.insert(tile.ID, tile.IDBig); + + continue; + float ratio = float(tile.ID) / float(tile.IDBig); + if (tile.layerID == 1 && tile.ID * 10000 != tile.IDBig) { if (ratio > 4.5e-5 && tile.IDBig < 9000000) { ids.insert(tile.ID, tile.IDBig); @@ -898,6 +1030,7 @@ } } } + if (tile.layerID == 1 && tile.ID == 324 && tile.IDBig < 9000000) { qDebug() << field->name(); qDebug() << QString("tileID=%1, layer=%2, param=%3, state=%4\n") @@ -924,26 +1057,115 @@ .arg(tile.IDBig).toUtf8(); } } - // qDebug() << field->name() << field->scriptsAndTexts()->scale(); } } + break; } - foreach (int ID, ids.uniqueKeys()) { + for (int ID : ids.uniqueKeys()) { QList zBigs = ids.values(ID); QList zBigsUnique = zBigs.toSet().toList(); - qSort(zBigsUnique); - foreach (quint32 zBig, zBigsUnique) { - qDebug() << qPrintable(QString("%1\t%2\t%3\t%4").arg(ID).arg(zBig).arg(zBigs.count(zBig)).arg(float(ID) / float(zBig))); + std::sort(zBigsUnique.begin(), zBigsUnique.end()); + for (quint32 zBig : zBigsUnique) { + deb2.write(QString("%1,%2\n").arg(ID).arg(zBig).toLatin1()); } } + + deb2.close(); } void FieldArchive::searchAll() { QTime t;t.start(); + /* QFile deb1("encounters-scripts.txt"); + deb1.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); + deb1.write("field name,encounter,group ID,script ID,opcode ID\n"); */ + + FieldArchiveIterator it1(*this); + while (it1.hasNext()) { + Field *field = it1.next(true, true); + if (field && field->isOpen()) { + /* Section1File *scripts = field->scriptsAndTexts(); + if (scripts->isOpen()) { + int groupID=0, scriptID=0, opcodeID=0; + while (scripts->searchOpcode(int(Opcode::BATTLE), groupID, scriptID, opcodeID)) { + OpcodeBATTLE *op = (OpcodeBATTLE *)scripts->grpScript(groupID)->script(quint8(scriptID))->opcode(quint16(opcodeID)); + deb1.write((field->name() % "," % QString::number(op->battleID) % "," % QString::number(groupID) % "," % QString::number(scriptID) % "," % QString::number(opcodeID) % "\n").toLocal8Bit()); + opcodeID += 1; + } + } */ + FieldModelLoader *modelLoader = field->fieldModelLoader(); + if (modelLoader && modelLoader->isOpen() && field->isPC()) { + FieldModelLoaderPC *modelLoaderPc = (FieldModelLoaderPC *)modelLoader; + for (int i = 0; i < modelLoaderPc->modelCount(); i++) { + FieldModelInfosPC infos = modelLoaderPc->modelInfos(i); + if (infos.nameHRC == "AAAA.HRC" && infos.typeHRC >= 1024) { + qDebug() << qPrintable(field->name()) << infos.typeHRC; + } + } + } + /* EncounterFile *enc = field->encounter(); + if (enc && enc->isOpen()) { + for (EncounterFile::Table table : QList() << EncounterFile::Table1 << EncounterFile::Table2) { + const EncounterTable &ta = enc->encounterTable(table); + if (ta.enabled & 1) { + for (int i = 0; i < 6; i++) { + if (PROBABILITY(ta.enc_standard[i]) >= 32) { + qDebug() << qPrintable(field->name()) << PROBABILITY(ta.enc_standard[i]); + } + } + for (int i = 0; i < 4; i++) { + if (PROBABILITY(ta.enc_special[i]) >= 32) { + qDebug() << qPrintable(field->name()) << PROBABILITY(ta.enc_special[i]); + } + } + } + } + } */ + } + } + + // deb1.close(); + + return; + + /* QFile deb1("encounters.txt"); + deb1.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); + deb1.write("field name,encounter\n"); + + FieldArchiveIterator it1(*this); + while (it1.hasNext()) { + Field *field = it1.next(true, true); + if (field && field->isOpen()) { + EncounterFile *enc = field->encounter(); + if (enc->isOpen()) { + for (EncounterFile::Table table : QList() << EncounterFile::Table1 << EncounterFile::Table2) { + const EncounterTable &ta = enc->encounterTable(table); + if (ta.enabled & 1) { + for (int i = 0; i < 6; i++) { + if (BATTLE_ID(ta.enc_standard[i]) > 0 && PROBABILITY(ta.enc_standard[i]) > 0) { + deb1.write((field->name() % "," % QString::number(BATTLE_ID(ta.enc_standard[i])) % "\n").toLocal8Bit()); + } + } + for (int i = 0; i < 4; i++) { + if (BATTLE_ID(ta.enc_special[i]) > 0 && PROBABILITY(ta.enc_special[i]) > 0) { + deb1.write((field->name() % "," % QString::number(BATTLE_ID(ta.enc_special[i])) % "\n").toLocal8Bit()); + } + } + + } + } + + } + } + } + + deb1.close(); + + return; */ + QFile deb(QString("scripts-unlocked-talk-P%1.txt").arg(isPC() ? "C" : "S")); deb.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate); @@ -964,13 +1186,13 @@ /*Section1File *section1 = field->scriptsAndTexts(); if (section1->isOpen()) { int groupID = 0; - foreach (GrpScript *grp, section1->grpScripts()) { + for (GrpScript *grp : section1->grpScripts()) { if (grp->typeID() == GrpScript::Model || grp->typeID() == GrpScript::Location) { Script *talkScript = grp->script(2); // Talk bool disableMovability = false, disableMenus = false, saySomething = false; - foreach (Opcode *op, talkScript->opcodes()) { + for (Opcode *op : talkScript->opcodes()) { if (op->id() == Opcode::UC) { disableMovability = true; } else if (op->id() == Opcode::MENU2) { @@ -1003,25 +1225,25 @@ return; FieldArchivePC original("C:/Program Files/Square Soft, Inc/Final Fantasy VII/data/field/fflevel - original.lgp", FieldArchiveIO::Lgp); - if(original.open() != FieldArchiveIO::Ok) { + if (original.open() != FieldArchiveIO::Ok) { qWarning() << "error opening pc lgp"; return; } /*FieldArchivePS ps("C:/Users/Jérôme/Games/Final Fantasy VII-PSX-PAL-FR-CD1.bin", FieldArchiveIO::Iso); - if(ps.open() != FieldArchiveIO::Ok) { + if (ps.open() != FieldArchiveIO::Ok) { qWarning() << "error opening ps iso"; return; } - if(!isPC()) { + if (!isPC()) { return; } Field *f1 = this->field(fieldsSortByName.value("yougan"), true); - if(f1) { + if (f1) { Section1File *f1s1 = f1->scriptsAndTexts(); - if(f1s1->isOpen()) { + if (f1s1->isOpen()) { int groupScriptCount = f1s1->grpScriptCount(); for (int groupScriptID=0; groupScriptID < groupScriptCount; groupScriptID++) { @@ -1047,57 +1269,58 @@ }*/ QSet screens; -// for(int i=0 ; ifield(i, true); +// for (int i=0; iname())); - if(fieldOriginal == NULL) { + if (fieldOriginal == nullptr) { qWarning() << "ALERT field not found" << field->name(); break; } - if(field != NULL) { + if (field != nullptr) { Section1File *scriptsAndTexts = field->scriptsAndTexts(); Section1File *scriptsAndTextsOriginal = fieldOriginal->scriptsAndTexts(); - if(scriptsAndTexts->isOpen() && scriptsAndTextsOriginal->isOpen()) { + if (scriptsAndTexts->isOpen() && scriptsAndTextsOriginal->isOpen()) { qWarning() << field->name(); - if(scriptsAndTexts->grpScriptCount() < scriptsAndTextsOriginal->grpScriptCount()) { + if (scriptsAndTexts->grpScriptCount() < scriptsAndTextsOriginal->grpScriptCount()) { qWarning() << "ALERT much grpscript wow"; break; } int grpScriptID = 0, scriptID; - foreach(GrpScript *group2, scriptsAndTextsOriginal->grpScripts()) { + for (GrpScript *group2 : scriptsAndTextsOriginal->grpScripts()) { GrpScript *grp = scriptsAndTexts->grpScript(grpScriptID); - while(group2->name() != grp->name()) { + while (group2->name() != grp->name()) { grpScriptID++; - if(grpScriptID >= scriptsAndTexts->grpScriptCount()) { + if (grpScriptID >= scriptsAndTexts->grpScriptCount()) { qWarning() << "ALERT end grpScript reached"; goto next_group; } grp = scriptsAndTexts->grpScript(grpScriptID); } - if(grp->size() != group2->size()) { + if (grp->size() != group2->size()) { qWarning() << "ALERT wrong group size" << grp->size() << group2->size(); break; } scriptID = 0; - foreach(Script *script2, group2->scripts()) { + for (Script *script2 : group2->scripts()) { Script *script = grp->script(scriptID); int opcodeID = 0; - foreach(Opcode *opcode2, script2->opcodes()) { + for (Opcode *opcode2 : script2->opcodes()) { FF7Window win, win2; - if(opcode2->getWindow(win2)) { + if (opcode2->getWindow(win2)) { Opcode *opcode; do { - if(opcodeID >= script->size()) { + if (opcodeID >= script->size()) { qWarning() << "ALERT wrong script size"; goto next_script; } @@ -1112,7 +1335,7 @@ hasTinyDiffY = diffY >= minDiff && diffY <= maxDiff, hasLargeDiffX = diffX > 15,//maxDiff, hasLargeDiffY = diffY > 15;//maxDiff; - if((hasTinyDiffX && hasLargeDiffY) || (hasTinyDiffY && hasLargeDiffX)) { + if ((hasTinyDiffX && hasLargeDiffY) || (hasTinyDiffY && hasLargeDiffX)) { deb.write(QString("%1 > %2 > %3: window %4 (retraduit: %5, %6) (original: %7, %8)\n") .arg(field->name()) .arg(grp->name()) @@ -1134,17 +1357,17 @@ } qDebug() << screens.size() << "écrans"; /*QString fieldDir = QString("%1-%2").arg(Data::field_names.indexOf(field->name()), 3, 10, QChar('0')).arg(field->name()); - if(!tmp.mkdir(fieldDir)) { + if (!tmp.mkdir(fieldDir)) { qWarning() << "cannot create dir" << tmp.absoluteFilePath(fieldDir); } tmp.cd(fieldDir); scriptsAndTexts->clearTexts(); int grpScriptID = 0; - foreach(GrpScript *grp, scriptsAndTexts->grpScripts()) { + for (GrpScript *grp : scriptsAndTexts->grpScripts()) { QString grpFilename = QString("%1-%2").arg(grpScriptID).arg(grp->name()); QFile out(tmp.absoluteFilePath(grpFilename)); - if(out.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { + if (out.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { out.write(grp->toString(field).toLatin1()); out.close(); } @@ -1153,10 +1376,10 @@ tmp.cdUp();*/ /*QFile out(tmp.absoluteFilePath(fieldDir)); - if(out.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { + if (out.open(QIODevice::WriteOnly | QIODevice::Text | QIODevice::Truncate)) { int textID = 0; - foreach(const FF7Text &text, scriptsAndTexts->texts()) { + for (const FF7Text &text : scriptsAndTexts->texts()) { out.write(QString("=== Texte %1 ===\n").arg(textID++).toLatin1()); out.write(text.text(false).toLatin1()); out.write("\n"); @@ -1167,13 +1390,13 @@ } /*FieldPC *fieldPC = (FieldPC *)field; FieldModelLoaderPC *modelLoader = fieldPC->fieldModelLoader(); - if(modelLoader->isOpen()) { + if (modelLoader->isOpen()) { int modelID = 0; - foreach(const QString &HRC, modelLoader->HRCNames()) { - foreach(const QString &a, modelLoader->ANames(modelID)) { + for (const QString &HRC : modelLoader->HRCNames()) { + for (const QString &a : modelLoader->ANames(modelID)) { FieldModelFilePC *fieldModel = fieldPC->fieldModel(HRC, a); - if(fieldModel->isOpen()) { - if(fieldModel->animBoneCount() > 1 && fieldModel->animBoneCount() != fieldModel->boneCount()) { + if (fieldModel->isOpen()) { + if (fieldModel->animBoneCount() > 1 && fieldModel->animBoneCount() != fieldModel->boneCount()) { qDebug() << field->name() << modelID << HRC << a << fieldModel->animBoneCount() << fieldModel->boneCount(); } } else { @@ -1193,72 +1416,56 @@ #endif -bool FieldArchive::searchIterators(QMap::const_iterator &i, QMap::const_iterator &end, int fieldID, Sorting sorting, SearchScope scope) const -{ - if(fieldID >= fileList.size()) return false; - - switch(sorting) { - case SortByName: - i = fieldsSortByName.constFind(fieldsSortByName.key(fieldID), fieldID); - end = fieldsSortByName.constEnd(); - if(i == end) { - i = fieldsSortByName.constBegin(); - } - break; - case SortByMapId: - i = fieldsSortByMapId.constFind(fieldsSortByMapId.key(fieldID), fieldID); - end = fieldsSortByMapId.constEnd(); - if(i == end) { - i = fieldsSortByMapId.constBegin(); - } - break; - } - - if(scope >= FieldScope && fieldID != i.value()) { - return false; - } - - return true; -} - bool FieldArchive::find(bool (*predicate)(Field *, SearchQuery *, SearchIn *), - SearchQuery *toSearch, int &fieldID, SearchIn *searchIn, + SearchQuery *toSearch, int &mapID, SearchIn *searchIn, Sorting sorting, SearchScope scope) { - QMap::const_iterator i, end; - if(!searchIterators(i, end, fieldID, sorting, scope)) return false; + Q_UNUSED(sorting) + FieldArchiveIterator it(*this); + if (!it.seek(mapID)) { + return false; + } - for( ; i != end ; ++i) { - QCoreApplication::processEvents(); - Field *f = field(fieldID = i.value()); - if(f!=NULL && (*predicate)(f, toSearch, searchIn)) + while (it.hasNext()) { + Field *f = it.next(); + mapID = it.mapId(); + if (f != nullptr && (*predicate)(f, toSearch, searchIn)) { return true; + } searchIn->reset(); - if(scope >= FieldScope) break; + if (scope >= FieldScope) { + break; + } } return false; } bool FieldArchive::findLast(bool (*predicate)(Field *, SearchQuery *, SearchIn *), - SearchQuery *toSearch, int &fieldID, SearchIn *searchIn, + SearchQuery *toSearch, int &mapID, SearchIn *searchIn, Sorting sorting, SearchScope scope) { - QMap::const_iterator i, begin; - if(!searchIteratorsP(i, begin, fieldID, sorting, scope)) return false; + Q_UNUSED(sorting) + FieldArchiveIterator it(*this); + if (!it.seek(mapID)) { + return false; + } - for( ; i != begin-1 ; --i) - { - QCoreApplication::processEvents(); - Field *f = field(fieldID = i.value()); - if(f!=NULL && (*predicate)(f, toSearch, searchIn)) + while (it.hasPrevious()) { + Field *f = it.previous(); + mapID = it.key(); + if (f != nullptr && (*predicate)(f, toSearch, searchIn)) { return true; + } searchIn->toEnd(); - if(scope >= FieldScope) break; + if (scope >= FieldScope) { + break; + } } + return false; } -bool FieldArchive::searchOpcode(int opcode, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) +bool FieldArchive::searchOpcode(int opcode, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) { SearchOpcodeQuery query(opcode); SearchInScript searchIn(groupID, scriptID, opcodeID); @@ -1267,10 +1474,10 @@ SearchOpcodeQuery *query = static_cast(_query); SearchInScript *searchIn = static_cast(_searchIn); return f->scriptsAndTexts()->searchOpcode(query->opcode, searchIn->groupID, searchIn->scriptID, searchIn->opcodeID); - }, &query, fieldID, &searchIn, sorting, scope); + }, &query, mapID, &searchIn, sorting, scope); } -bool FieldArchive::searchVar(quint8 bank, quint16 address, Opcode::Operation op, int value, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) +bool FieldArchive::searchVar(quint8 bank, quint16 address, Opcode::Operation op, int value, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) { SearchVarQuery query(bank, address, op, value); SearchInScript searchIn(groupID, scriptID, opcodeID); @@ -1279,10 +1486,10 @@ SearchVarQuery *query = static_cast(_query); SearchInScript *searchIn = static_cast(_searchIn); return f->scriptsAndTexts()->searchVar(query->bank, query->address, query->op, query->value, searchIn->groupID, searchIn->scriptID, searchIn->opcodeID); - }, &query, fieldID, &searchIn, sorting, scope); + }, &query, mapID, &searchIn, sorting, scope); } -bool FieldArchive::searchExec(quint8 group, quint8 script, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) +bool FieldArchive::searchExec(quint8 group, quint8 script, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) { SearchExecQuery query(group, script); SearchInScript searchIn(groupID, scriptID, opcodeID); @@ -1291,10 +1498,10 @@ SearchExecQuery *query = static_cast(_query); SearchInScript *searchIn = static_cast(_searchIn); return f->scriptsAndTexts()->searchExec(query->group, query->script, searchIn->groupID, searchIn->scriptID, searchIn->opcodeID); - }, &query, fieldID, &searchIn, sorting, scope); + }, &query, mapID, &searchIn, sorting, scope); } -bool FieldArchive::searchMapJump(quint16 _field, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) +bool FieldArchive::searchMapJump(int _field, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) { SearchFieldQuery query(_field); SearchInScript searchIn(groupID, scriptID, opcodeID); @@ -1302,11 +1509,11 @@ return find([](Field *f, SearchQuery *_query, SearchIn *_searchIn) { SearchFieldQuery *query = static_cast(_query); SearchInScript *searchIn = static_cast(_searchIn); - return f->scriptsAndTexts()->searchMapJump(query->fieldID, searchIn->groupID, searchIn->scriptID, searchIn->opcodeID); - }, &query, fieldID, &searchIn, sorting, scope); + return f->scriptsAndTexts()->searchMapJump(query->mapID, searchIn->groupID, searchIn->scriptID, searchIn->opcodeID); + }, &query, mapID, &searchIn, sorting, scope); } -bool FieldArchive::searchTextInScripts(const QRegExp &text, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) +bool FieldArchive::searchTextInScripts(const QRegExp &text, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) { SearchTextQuery query(text); SearchInScript searchIn(groupID, scriptID, opcodeID); @@ -1315,10 +1522,10 @@ SearchTextQuery *query = static_cast(_query); SearchInScript *searchIn = static_cast(_searchIn); return f->scriptsAndTexts()->searchTextInScripts(query->text, searchIn->groupID, searchIn->scriptID, searchIn->opcodeID); - }, &query, fieldID, &searchIn, sorting, scope); + }, &query, mapID, &searchIn, sorting, scope); } -bool FieldArchive::searchText(const QRegExp &text, int &fieldID, int &textID, int &from, int &size, Sorting sorting, SearchScope scope) +bool FieldArchive::searchText(const QRegExp &text, int &mapID, int &textID, int &from, int &size, Sorting sorting, SearchScope scope) { SearchTextQuery query(text); int empty; @@ -1328,38 +1535,10 @@ SearchTextQuery *query = static_cast(_query); SearchInText *searchIn = static_cast(_searchIn); return f->scriptsAndTexts()->searchText(query->text, searchIn->textID, searchIn->from, searchIn->size); - }, &query, fieldID, &searchIn, sorting, scope); + }, &query, mapID, &searchIn, sorting, scope); } -bool FieldArchive::searchIteratorsP(QMap::const_iterator &i, QMap::const_iterator &begin, int fieldID, Sorting sorting, SearchScope scope) const -{ - if(fieldID < 0) return false; - - switch(sorting) { - case SortByName: - begin = fieldsSortByName.constBegin(); - i = fieldsSortByName.constFind(fieldsSortByName.key(fieldID), fieldID); - if(i==fieldsSortByName.constEnd()) { - --i; - } - break; - case SortByMapId: - begin = fieldsSortByMapId.constBegin(); - i = fieldsSortByMapId.constFind(fieldsSortByMapId.key(fieldID), fieldID); - if(i==fieldsSortByMapId.constEnd()) { - --i; - } - break; - } - - if(scope >= FieldScope && fieldID != i.value()) { - return false; - } - - return true; -} - -bool FieldArchive::searchOpcodeP(int opcode, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) +bool FieldArchive::searchOpcodeP(int opcode, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) { SearchOpcodeQuery query(opcode); SearchInScript searchIn(groupID, scriptID, opcodeID); @@ -1368,10 +1547,10 @@ SearchOpcodeQuery *query = static_cast(_query); SearchInScript *searchIn = static_cast(_searchIn); return f->scriptsAndTexts()->searchOpcodeP(query->opcode, searchIn->groupID, searchIn->scriptID, searchIn->opcodeID); - }, &query, fieldID, &searchIn, sorting, scope); + }, &query, mapID, &searchIn, sorting, scope); } -bool FieldArchive::searchVarP(quint8 bank, quint16 address, Opcode::Operation op, int value, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) +bool FieldArchive::searchVarP(quint8 bank, quint16 address, Opcode::Operation op, int value, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) { SearchVarQuery query(bank, address, op, value); SearchInScript searchIn(groupID, scriptID, opcodeID); @@ -1380,10 +1559,10 @@ SearchVarQuery *query = static_cast(_query); SearchInScript *searchIn = static_cast(_searchIn); return f->scriptsAndTexts()->searchVarP(query->bank, query->address, query->op, query->value, searchIn->groupID, searchIn->scriptID, searchIn->opcodeID); - }, &query, fieldID, &searchIn, sorting, scope); + }, &query, mapID, &searchIn, sorting, scope); } -bool FieldArchive::searchExecP(quint8 group, quint8 script, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) +bool FieldArchive::searchExecP(quint8 group, quint8 script, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) { SearchExecQuery query(group, script); SearchInScript searchIn(groupID, scriptID, opcodeID); @@ -1392,10 +1571,10 @@ SearchExecQuery *query = static_cast(_query); SearchInScript *searchIn = static_cast(_searchIn); return f->scriptsAndTexts()->searchExecP(query->group, query->script, searchIn->groupID, searchIn->scriptID, searchIn->opcodeID); - }, &query, fieldID, &searchIn, sorting, scope); + }, &query, mapID, &searchIn, sorting, scope); } -bool FieldArchive::searchMapJumpP(quint16 _field, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) +bool FieldArchive::searchMapJumpP(int _field, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) { SearchFieldQuery query(_field); SearchInScript searchIn(groupID, scriptID, opcodeID); @@ -1403,11 +1582,11 @@ return findLast([](Field *f, SearchQuery *_query, SearchIn *_searchIn) { SearchFieldQuery *query = static_cast(_query); SearchInScript *searchIn = static_cast(_searchIn); - return f->scriptsAndTexts()->searchMapJumpP(query->fieldID, searchIn->groupID, searchIn->scriptID, searchIn->opcodeID); - }, &query, fieldID, &searchIn, sorting, scope); + return f->scriptsAndTexts()->searchMapJumpP(query->mapID, searchIn->groupID, searchIn->scriptID, searchIn->opcodeID); + }, &query, mapID, &searchIn, sorting, scope); } -bool FieldArchive::searchTextInScriptsP(const QRegExp &text, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) +bool FieldArchive::searchTextInScriptsP(const QRegExp &text, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope) { SearchTextQuery query(text); SearchInScript searchIn(groupID, scriptID, opcodeID); @@ -1416,10 +1595,10 @@ SearchTextQuery *query = static_cast(_query); SearchInScript *searchIn = static_cast(_searchIn); return f->scriptsAndTexts()->searchTextInScriptsP(query->text, searchIn->groupID, searchIn->scriptID, searchIn->opcodeID); - }, &query, fieldID, &searchIn, sorting, scope); + }, &query, mapID, &searchIn, sorting, scope); } -bool FieldArchive::searchTextP(const QRegExp &text, int &fieldID, int &textID, int &from, int &index, int &size, Sorting sorting, SearchScope scope) +bool FieldArchive::searchTextP(const QRegExp &text, int &mapID, int &textID, int &from, int &index, int &size, Sorting sorting, SearchScope scope) { SearchTextQuery query(text); SearchInText searchIn(textID, from, size, index); @@ -1428,17 +1607,17 @@ SearchTextQuery *query = static_cast(_query); SearchInText *searchIn = static_cast(_searchIn); return f->scriptsAndTexts()->searchTextP(query->text, searchIn->textID, searchIn->from, searchIn->index, searchIn->size); - }, &query, fieldID, &searchIn, sorting, scope); + }, &query, mapID, &searchIn, sorting, scope); } -bool FieldArchive::replaceText(const QRegExp &search, const QString &after, int fieldID, int textID, int from) +bool FieldArchive::replaceText(const QRegExp &search, const QString &after, int mapID, int textID, int from) { - if(textID > -1) { - Field *field = this->field(fieldID); - if(field) { + if (textID > -1) { + Field *field = this->field(mapID); + if (field) { Section1File *texts = field->scriptsAndTexts(); - if(texts->isOpen() && textID < texts->textCount()) { - if(texts->replaceText(search, after, textID, from)) { + if (texts->isOpen() && textID < texts->textCount()) { + if (texts->replaceText(search, after, textID, from)) { return true; } } @@ -1447,16 +1626,17 @@ return false; } -bool FieldArchive::compileScripts(int &fieldID, int &groupID, int &scriptID, int &opcodeID, QString &errorStr) +bool FieldArchive::compileScripts(int &mapID, int &groupID, int &scriptID, int &opcodeID, QString &errorStr) { - int size = fileList.size(); + FieldArchiveIterator it(*this); - for(fieldID=0 ; fieldIDfield(fieldID, false); - if(field != NULL && field->isOpen()) { + Field *field = it.next(false); + mapID = it.mapId(); + if (field != nullptr && field->isOpen()) { Section1File *section1 = field->scriptsAndTexts(); - if(section1->isOpen() && !section1->compileScripts(groupID, scriptID, opcodeID, errorStr)) { + if (section1->isOpen() && !section1->compileScripts(groupID, scriptID, opcodeID, errorStr)) { return false; } } @@ -1467,66 +1647,98 @@ void FieldArchive::removeBattles() { + FieldArchiveIterator it(*this); + int i = 0; + observer()->setObserverMaximum(fileList.size()); - for(int fieldID=0 ; fieldIDobserverWasCanceled()) { + while (it.hasNext()) { + if (observer()->observerWasCanceled()) { return; } - Field *field = this->field(fieldID, true); - if(field != NULL && field->scriptsAndTexts()->isOpen()) { + Field *field = it.next(); + if (field != nullptr && field->scriptsAndTexts()->isOpen()) { field->encounter()->setBattleEnabled(EncounterFile::Table1, false); field->encounter()->setBattleEnabled(EncounterFile::Table2, false); - if(!field->isModified()) { + if (!field->isModified()) { field->setModified(true); } } - observer()->setObserverValue(fieldID); + observer()->setObserverValue(i++); } } void FieldArchive::removeTexts() { + FieldArchiveIterator it(*this); + int i = 0; + observer()->setObserverMaximum(fileList.size()); - for(int fieldID=0 ; fieldIDobserverWasCanceled()) { + while (it.hasNext()) { + if (observer()->observerWasCanceled()) { return; } - Field *field = this->field(fieldID, true); - if(field != NULL && field->scriptsAndTexts()->isOpen()) { + Field *field = it.next(); + if (field != nullptr && field->scriptsAndTexts()->isOpen()) { field->scriptsAndTexts()->removeTexts(); - if(field->scriptsAndTexts()->isModified() && !field->isModified()) { + if (field->scriptsAndTexts()->isModified() && !field->isModified()) { field->setModified(true); } } - observer()->setObserverValue(fieldID); + observer()->setObserverValue(i++); } } void FieldArchive::cleanTexts() { + FieldArchiveIterator it(*this); + int i = 0; + observer()->setObserverMaximum(fileList.size()); - for(int fieldID=0 ; fieldIDobserverWasCanceled()) { + while (it.hasNext()) { + if (observer()->observerWasCanceled()) { return; } - Field *field = this->field(fieldID, true); - if(field != NULL && field->scriptsAndTexts()->isOpen()) { + Field *field = it.next(); + if (field != nullptr && field->scriptsAndTexts()->isOpen()) { field->scriptsAndTexts()->cleanTexts(); - if(field->scriptsAndTexts()->isModified() && !field->isModified()) { + if (field->scriptsAndTexts()->isModified() && !field->isModified()) { + field->setModified(true); + } + } + observer()->setObserverValue(i++); + } +} + +void FieldArchive::autosizeTextWindows() +{ + FieldArchiveIterator it(*this); + int i = 0; + + observer()->setObserverMaximum(fileList.size()); + + while (it.hasNext()) { + if (observer()->observerWasCanceled()) { + return; + } + Field *field = it.next(); + if (field != nullptr && field->scriptsAndTexts()->isOpen()) { + field->scriptsAndTexts()->autosizeTextWindows(); + if (field->scriptsAndTexts()->isModified() && !field->isModified()) { field->setModified(true); } } - observer()->setObserverValue(fieldID); + observer()->setObserverValue(i++); } } bool FieldArchive::exportation(const QList &selectedFields, const QString &directory, - bool overwrite, const QMap &toExport) + bool overwrite, const QMap &toExport, + PsfTags *tags) { - if(selectedFields.isEmpty() || toExport.isEmpty()) { + if (selectedFields.isEmpty() || toExport.isEmpty()) { return true; } @@ -1534,50 +1746,55 @@ int currentField=0; observer()->setObserverMaximum(selectedFields.size()-1); - foreach(const int &fieldID, selectedFields) { - if(observer()->observerWasCanceled()) break; - Field *f = field(fieldID); - if(f) { - if(toExport.contains(Fields)) { + for (const int &mapID : selectedFields) { + if (observer()->observerWasCanceled()) break; + Field *f = field(mapID); + if (f) { + if (toExport.contains(Fields)) { extension = toExport.value(Fields); path = QDir::cleanPath(extension.isEmpty() ? QString("%1/%2") .arg(directory, f->name()) : QString("%1/%2.%3") .arg(directory, f->name(), extension)); - if(overwrite || !QFile::exists(path)) { + if (overwrite || !QFile::exists(path)) { QByteArray fieldData = io()->fieldData(f, io()->isPC() ? QString() : "DAT", extension.compare("dec", Qt::CaseInsensitive) == 0); - if(!fieldData.isEmpty()) { + if (!fieldData.isEmpty()) { QFile fieldExport(path); - if(fieldExport.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + if (fieldExport.open(QIODevice::WriteOnly | QIODevice::Truncate)) { fieldExport.write(fieldData); fieldExport.close(); } } } } - if(toExport.contains(Backgrounds)) { + if (toExport.contains(Backgrounds)) { extension = toExport.value(Backgrounds); path = QDir::cleanPath(QString("%1/%2.%3").arg(directory, f->name(), extension)); - if(overwrite || !QFile::exists(path)) { + if (overwrite || !QFile::exists(path)) { QImage background = f->background()->openBackground(); - if(!background.isNull()) + if (!background.isNull()) background.save(path); } } - if(toExport.contains(Akaos)) { + if (toExport.contains(Akaos)) { TutFileStandard *akaoList = f->tutosAndSounds(); - if(akaoList->isOpen()) { + if (akaoList->isOpen()) { int akaoCount = akaoList->size(); - for(int i=0 ; iisTut(i)) { + for (int i=0; iisTut(i)) { extension = toExport.value(Akaos); - path = QDir::cleanPath(QString("%1/%2-%3.%4").arg(directory, f->name()).arg(i).arg(extension)); - if(overwrite || !QFile::exists(path)) { + path = QDir::cleanPath(QString("%1/%2.%3").arg(directory, Data::music_names.value(akaoList->akaoID(i), f->name()), extension)); + if (overwrite || !QFile::exists(path)) { QFile tutExport(path); - if(tutExport.open(QIODevice::WriteOnly | QIODevice::Truncate)) { - tutExport.write(akaoList->data(i)); + if (tutExport.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + if (extension == "minipsf") { + tags->setTitle(Data::music_desc.value(akaoList->akaoID(i), f->name())); + tutExport.write(PsfFile::fromAkao(akaoList->data(i), *tags).save()); + } else { + tutExport.write(akaoList->data(i)); + } tutExport.close(); } } @@ -1585,23 +1802,23 @@ } } } - if(toExport.contains(Texts)) { + if (toExport.contains(Texts)) { Section1File *section1 = f->scriptsAndTexts(); - if(section1->isOpen()) { + if (section1->isOpen()) { extension = toExport.value(Texts); path = QDir::cleanPath(QString("%1/%2.%3").arg(directory, f->name(), extension)); - if(overwrite || !QFile::exists(path)) { + if (overwrite || !QFile::exists(path)) { QFile textExport(path); Section1File::ExportFormat format; - if(extension == "txt") { + if (extension == "txt") { format = Section1File::TXTText; - } else if(extension == "xml") { + } else if (extension == "xml") { format = Section1File::XMLText; } else { return false; } - if(!section1->exporter(&textExport, format)) { + if (!section1->exporter(&textExport, format)) { return false; } } @@ -1619,19 +1836,19 @@ { Q_UNUSED(directory) //TODO - if(selectedFields.isEmpty() || toImport.isEmpty()) { + if (selectedFields.isEmpty() || toImport.isEmpty()) { return true; } int currentField=0; - foreach(const int &fieldID, selectedFields) { - if(observer()->observerWasCanceled()) break; + for (const int &mapID : selectedFields) { + if (observer()->observerWasCanceled()) break; - Field *f = field(fieldID); - if(f) { - if(toImport.contains(Field::Scripts)) { + Field *f = field(mapID); + if (f) { + if (toImport.contains(Field::Scripts)) { Section1File *section1 = f->scriptsAndTexts(); - if(section1->isOpen()) { + if (section1->isOpen()) { //TODO } } @@ -1644,7 +1861,7 @@ void FieldArchive::setSaved() { - foreach(Field *field, fileList) { + for (Field *field : qAsConst(fileList)) { field->setSaved(); } } diff -Nru makoureactor-1.7.2/core/field/FieldArchive.h makoureactor-1.8.0/core/field/FieldArchive.h --- makoureactor-1.7.2/core/field/FieldArchive.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldArchive.h 2020-08-08 18:46:56.000000000 +0000 @@ -23,6 +23,7 @@ #include #include "FieldArchiveIO.h" #include "Field.h" +#include "core/PsfFile.h" struct SearchQuery { @@ -54,9 +55,9 @@ struct SearchFieldQuery : public SearchQuery { - quint16 fieldID; - explicit SearchFieldQuery(quint16 fieldID) : - fieldID(fieldID) {} + int mapID; + explicit SearchFieldQuery(int mapID) : + mapID(mapID) {} }; struct SearchTextQuery : public SearchQuery @@ -110,17 +111,22 @@ class FieldArchive; -class FieldArchiveIterator : public QListIterator +class FieldArchiveIterator : public QMapIterator { friend class FieldArchive; public: explicit FieldArchiveIterator(const FieldArchive &archive); + bool seek(int mapId); Field *next(bool open=true, bool dontOptimize=false); Field *peekNext(bool open=true, bool dontOptimize=false) const; Field *peekPrevious(bool open=true, bool dontOptimize=false) const; Field *previous(bool open=true, bool dontOptimize=false); + inline int mapId() const { + return key(); + } private: static Field *openField(Field *field, bool open=true, bool dontOptimize=false); + QMap mapList; }; class FieldArchive @@ -154,14 +160,13 @@ inline int size() const { return fileList.size(); } - int indexOfField(const QString &name) const; - const Field *field(quint32 id) const; - Field *field(quint32 id, bool open=true, bool dontOptimize=false); + const Field *field(quint32 mapId) const; + Field *field(quint32 mapId, bool open=true, bool dontOptimize=false); const Field *field(const QString &name) const; Field *field(const QString &name, bool open=true, bool dontOptimize=false); - void appendField(Field *field); - FieldArchiveIO::ErrorCode addField(Field *field, const QString &fileName, int &fieldId); - void removeField(quint32 id); + int appendField(Field *field); + void addNewField(Field *field, int &mapID); + void delField(int id); bool isAllOpened() const; bool isModified() const; @@ -171,42 +176,45 @@ void validateOneLineSize(); void printAkaos(const QString &filename); void printModelLoaders(const QString &filename, bool generic = true); - void printTexts(const QString &filename); + void printTexts(const QString &filename, bool usedTexts = false); + void printTextsDir(const QString &dirname, bool usedTexts = false); void compareTexts(FieldArchive *other); void printScripts(const QString &filename); void printScriptsDirs(const QString &filename); void diffScripts(); - static bool printBackgroundTiles(Field *field, const QString &filename, bool uniformize = false); - void searchBackgroundZ(); + bool printBackgroundTiles(bool uniformize = false, bool fromUnusedPCSection = false); + void printBackgroundZ(); void searchAll();// research & debug function #endif bool find(bool (*predicate)(Field *, SearchQuery *, SearchIn *), - SearchQuery *toSearch, int &fieldID, SearchIn *searchIn, + SearchQuery *toSearch, int &mapID, SearchIn *searchIn, Sorting sorting, SearchScope scope); bool findLast(bool (*predicate)(Field *, SearchQuery *, SearchIn *), - SearchQuery *toSearch, int &fieldID, SearchIn *searchIn, + SearchQuery *toSearch, int &mapID, SearchIn *searchIn, Sorting sorting, SearchScope scope); - bool searchOpcode(int opcode, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); - bool searchVar(quint8 bank, quint16 address, Opcode::Operation op, int value, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); - bool searchExec(quint8 group, quint8 script, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); - bool searchMapJump(quint16 _field, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); - bool searchTextInScripts(const QRegExp &text, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); - bool searchText(const QRegExp &text, int &fieldID, int &textID, int &from, int &size, Sorting sorting, SearchScope scope); - bool searchOpcodeP(int opcode, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); - bool searchVarP(quint8 bank, quint16 address, Opcode::Operation op, int value, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); - bool searchExecP(quint8 group, quint8 script, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); - bool searchMapJumpP(quint16 _field, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); - bool searchTextInScriptsP(const QRegExp &text, int &fieldID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); - bool searchTextP(const QRegExp &text, int &fieldID, int &textID, int &from, int &index, int &size, Sorting sorting, SearchScope scope); - bool replaceText(const QRegExp &search, const QString &after, int fieldID, int textID, int from); + bool searchOpcode(int opcode, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); + bool searchVar(quint8 bank, quint16 address, Opcode::Operation op, int value, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); + bool searchExec(quint8 group, quint8 script, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); + bool searchMapJump(int _field, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); + bool searchTextInScripts(const QRegExp &text, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); + bool searchText(const QRegExp &text, int &mapID, int &textID, int &from, int &size, Sorting sorting, SearchScope scope); + bool searchOpcodeP(int opcode, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); + bool searchVarP(quint8 bank, quint16 address, Opcode::Operation op, int value, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); + bool searchExecP(quint8 group, quint8 script, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); + bool searchMapJumpP(int _field, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); + bool searchTextInScriptsP(const QRegExp &text, int &mapID, int &groupID, int &scriptID, int &opcodeID, Sorting sorting, SearchScope scope); + bool searchTextP(const QRegExp &text, int &mapID, int &textID, int &from, int &index, int &size, Sorting sorting, SearchScope scope); + bool replaceText(const QRegExp &search, const QString &after, int mapID, int textID, int from); - bool compileScripts(int &fieldID, int &groupID, int &scriptID, int &opcodeID, QString &errorStr); + bool compileScripts(int &mapID, int &groupID, int &scriptID, int &opcodeID, QString &errorStr); void removeBattles(); void removeTexts(); void cleanTexts(); + void autosizeTextWindows(); bool exportation(const QList &selectedFields, const QString &directory, - bool overwrite, const QMap &toExport); + bool overwrite, const QMap &toExport, + PsfTags *tags = nullptr); bool importation(const QList &selectedFields, const QString &directory, const QMap &toImport); @@ -222,14 +230,12 @@ return _observer; } private: + int indexOfField(const QString &name) const; void updateFieldLists(Field *field, int fieldID); - bool searchIterators(QMap::const_iterator &i, QMap::const_iterator &end, int fieldID, Sorting sorting, SearchScope scope) const; - bool searchIteratorsP(QMap::const_iterator &i, QMap::const_iterator &end, int fieldID, Sorting sorting, SearchScope scope) const; static bool openField(Field *field, bool dontOptimize=false); - QList fileList; + QMap fileList; QMultiMap fieldsSortByName; - QMultiMap fieldsSortByMapId; FieldArchiveIO *_io; ArchiveObserver *_observer; diff -Nru makoureactor-1.7.2/core/field/FieldArchiveIO.cpp makoureactor-1.8.0/core/field/FieldArchiveIO.cpp --- makoureactor-1.7.2/core/field/FieldArchiveIO.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldArchiveIO.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -42,11 +42,11 @@ QString FieldArchiveIO::name() const { - if(!hasName()) + if (!hasName()) return QString(); QString filePath = path(); - if(filePath.isEmpty()) { + if (filePath.isEmpty()) { return filePath; } @@ -55,11 +55,11 @@ QString FieldArchiveIO::directory() const { - if(!hasName()) + if (!hasName()) return path() + "/"; QString filePath = path(); - if(filePath.isEmpty()) { + if (filePath.isEmpty()) { return filePath; } @@ -69,7 +69,7 @@ QByteArray FieldArchiveIO::fieldData(Field *field, const QString &extension, bool unlzs) { // use data from the cache - if(unlzs && fieldDataIsCached(field, extension)) { + if (unlzs && fieldDataIsCached(field, extension)) { // qDebug() << "FieldArchive use field data from cache" << field->name(); return fieldDataCache; } /*else { @@ -79,7 +79,7 @@ QByteArray data = fieldData2(field, extension, unlzs); // put decompressed data in the cache - if(unlzs && !data.isEmpty()) { + if (unlzs && !data.isEmpty()) { fieldCache = field; fieldDataCache = data; fieldExtensionCache = extension; @@ -92,14 +92,14 @@ QByteArray data = fileData2(fileName); bool checkLzsHeader = !Config::value("lzsNotCheck").toBool(); - if(isLzsFile && (unlzs || checkLzsHeader)) { - if(data.size() < 4) return QByteArray(); + if (isLzsFile && (unlzs || checkLzsHeader)) { + if (data.size() < 4) return QByteArray(); const char *lzsDataConst = data.constData(); quint32 lzsSize; memcpy(&lzsSize, lzsDataConst, 4); - if(checkLzsHeader && (quint32)data.size() != lzsSize + 4) { + if (checkLzsHeader && (quint32)data.size() != lzsSize + 4) { return QByteArray(); } @@ -115,9 +115,9 @@ { QByteArray newData = fieldData(field, extension, unlzs); - if(!newData.isEmpty()) { + if (!newData.isEmpty()) { QFile fic(path); - if(!fic.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + if (!fic.open(QIODevice::WriteOnly | QIODevice::Truncate)) { return 2; } fic.write(newData); @@ -156,7 +156,7 @@ FieldArchiveIO::ErrorCode FieldArchiveIO::save(const QString &path, ArchiveObserver *observer) { ErrorCode error = save2(path, observer); - if(error == Ok) { + if (error == Ok) { clearCachedData(); // Important: the file data will change } return error; diff -Nru makoureactor-1.7.2/core/field/FieldArchiveIOPC.cpp makoureactor-1.8.0/core/field/FieldArchiveIOPC.cpp --- makoureactor-1.7.2/core/field/FieldArchiveIOPC.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldArchiveIOPC.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -39,7 +39,7 @@ FieldArchiveIO::ErrorCode FieldArchiveIOPCLgp::addField(const QString &fileName, const QString &name) { - if(_lgp.addFile(name, new QFile(fileName))) { + if (_lgp.addFile(name, new QFile(fileName))) { return FieldArchiveIO::Ok; } return FieldArchiveIO::FieldExists; @@ -63,9 +63,9 @@ QByteArray FieldArchiveIOPCLgp::fileData2(const QString &fileName) { - if(!_lgp.isOpen() && !_lgp.open()) return QByteArray(); + if (!_lgp.isOpen() && !_lgp.open()) return QByteArray(); QByteArray data = _lgp.fileData(fileName); - if(data.isEmpty()) { + if (data.isEmpty()) { return _lgp.modifiedFileData(fileName); } return data; @@ -79,44 +79,60 @@ FieldArchiveIO::ErrorCode FieldArchiveIOPCLgp::open2(ArchiveObserver *observer) { - if(!_lgp.isOpen() && !_lgp.open()) { + if (!_lgp.isOpen() && !_lgp.open()) { return ErrorOpening; } QStringList archiveList = _lgp.fileList(); - if(archiveList.isEmpty()) { + if (archiveList.isEmpty()) { return Invalid; } - if(observer) observer->setObserverMaximum(archiveList.size()); + if (observer) observer->setObserverMaximum(archiveList.size()); quint32 i, freq = archiveList.size()>50 ? archiveList.size()/50 : 1; + QString maplistName = "maplist"; + + if (!_lgp.fileExists(maplistName)) { + return FieldNotFound; + } + + if (!Data::openMaplist(_lgp.fileData(maplistName))) { + qWarning() << "Cannot open" << maplistName; + return FieldNotFound; + } + + QStringList maplist = Data::maplist(); // QTime t;t.start(); i = 0; - foreach(const QString &name, archiveList) { - if(i % freq == 0) { - if(observer) { - if(observer->observerWasCanceled()) { + for (const QString &name : qAsConst(archiveList)) { + if (i % freq == 0) { + if (observer) { + if (observer->observerWasCanceled()) { return Aborted; } observer->setObserverValue(i); } } - if(name.compare("maplist", Qt::CaseInsensitive) == 0) { - if(!Data::openMaplist(_lgp.fileData(name))) { - qWarning() << "Cannot open maplist!"; - } - } else if(name.endsWith(".tut", Qt::CaseInsensitive)) { + if (name.compare(maplistName, Qt::CaseInsensitive) == 0) { + } else if (name.endsWith(".tut", Qt::CaseInsensitive)) { fieldArchive()->addTut(name.toLower().left(name.size()-4)); - } else if(!name.contains('.')) { + } else if (!name.contains('.')) { fieldArchive()->appendField(new FieldPC(name, this)); + maplist.removeOne(name); ++i; } } + + // Adding missing fields + for (const QString &name : maplist.mid(65)) { + fieldArchive()->appendField(new FieldPC(name)); + } + // qDebug("Ouverture : %d ms", t.elapsed()); // qDebug() << FICHIER::size << " o"; // qDebug() << "nbGS : " << GrpScript::COUNT; @@ -129,39 +145,37 @@ FieldArchiveIO::ErrorCode FieldArchiveIOPCLgp::save2(const QString &path, ArchiveObserver *observer) { - if(!_lgp.isOpen() && !_lgp.open()) { + if (!_lgp.isOpen() && !_lgp.open()) { return ErrorOpening; } + FieldArchiveIterator it(*(fieldArchive())); bool oneFieldAdded = false; - for(int fieldID=0 ; fieldIDsize() ; ++fieldID) { - if(observer && observer->observerWasCanceled()) { + while (it.hasNext()) { + if (observer && observer->observerWasCanceled()) { return Aborted; } - Field *field = fieldArchive()->field(fieldID, false); - if(field && field->isOpen() && field->isModified()) { - if(_lgp.fileExists(field->name())) { - if(!_lgp.setFile(field->name(), new FieldSaveIO(field))) { + Field *field = it.next(false); + if (field && field->isOpen() && field->isModified()) { + if (_lgp.fileExists(field->name())) { + if (!_lgp.setFile(field->name(), new FieldSaveIO(field))) { return ErrorOpening; } + } else if (!_lgp.addFile(field->name(), new FieldSaveIO(field))) { + return ErrorOpening; } else { - return FieldNotFound; // TODO - if(!_lgp.addFile(field->name(), new FieldSaveIO(field))) { - return ErrorOpening; - } else { - oneFieldAdded = true; - } + oneFieldAdded = true; } } } - if(oneFieldAdded && _lgp.fileExists("maplist")) { - QStringList fieldNamesCopy = Data::field_names; + if (oneFieldAdded && _lgp.fileExists("maplist")) { + QStringList maplistCopy = Data::maplist(); // Check if the list was correctly opened before // FIXME - if(Data::openMaplist(_lgp.fileData("maplist"))) { - Data::field_names = fieldNamesCopy; + if (Data::openMaplist(_lgp.fileData("maplist"))) { + Data::setMaplist(maplistCopy); QByteArray mapListData; - if(Data::saveMaplist(mapListData)){ + if (Data::saveMaplist(mapListData)){ _lgp.setFileData("maplist", mapListData); } else { return Invalid; @@ -171,12 +185,12 @@ QMapIterator itTut(fieldArchive()->tuts()); - while(itTut.hasNext()) { + while (itTut.hasNext()) { itTut.next(); TutFile *tut = itTut.value(); - if(tut != NULL && tut->isModified()) { - if(!_lgp.setFileData(itTut.key() + ".tut", tut->save())) { + if (tut != nullptr && tut->isModified()) { + if (!_lgp.setFileData(itTut.key() + ".tut", tut->save())) { return FieldNotFound; } } @@ -184,11 +198,13 @@ this->observer = observer; - if(!_lgp.pack(path, this)) { + if (!_lgp.pack(path, this)) { this->observer = 0; - switch(_lgp.error()) { + switch (_lgp.error()) { case Lgp::OpenError: + return ErrorOpening; + case Lgp::OpenTempError: return ErrorOpeningTemp; case Lgp::InvalidError: return Invalid; @@ -222,7 +238,7 @@ Archive *FieldArchiveIOPCFile::device() { - return NULL; + return nullptr; } QByteArray FieldArchiveIOPCFile::fieldData2(Field *field, const QString &extension, bool unlzs) @@ -235,7 +251,7 @@ QByteArray FieldArchiveIOPCFile::fileData2(const QString &fileName) { Q_UNUSED(fileName) - if(!fic.isOpen() && !fic.open(QIODevice::ReadOnly)) return QByteArray(); + if (!fic.isOpen() && !fic.open(QIODevice::ReadOnly)) return QByteArray(); fic.reset(); QByteArray data = fic.readAll(); fic.close(); @@ -256,7 +272,9 @@ QString name = this->name(); fieldArchive()->appendField(new FieldPC(name.left(name.lastIndexOf('.')), this)); - Field *field = fieldArchive()->field(0); + // Open field + FieldArchiveIterator it(*(fieldArchive())); + Field *field = it.next(); return field && field->isOpen() ? Ok : Invalid; } @@ -266,12 +284,14 @@ Q_UNUSED(observer) QString path = path0.isNull() ? fic.fileName() : path0; - Field *field = fieldArchive()->field(0, false); - if(field && field->isOpen() && field->isModified()) { + FieldArchiveIterator it(*(fieldArchive())); + Field *field = it.next(false); + + if (field && field->isOpen() && field->isModified()) { qint8 err = field->save(path, true); - if(err == 2) return ErrorOpening; - if(err == 1) return Invalid; - if(err != 0) return NotImplemented; + if (err == 2) return ErrorOpening; + if (err == 1) return Invalid; + if (err != 0) return NotImplemented; } return Ok; @@ -289,7 +309,7 @@ Archive *FieldArchiveIOPCDir::device() { - return NULL; + return nullptr; } QByteArray FieldArchiveIOPCDir::fieldData2(Field *field, const QString &extension, bool unlzs) @@ -303,7 +323,7 @@ QByteArray data; QFile f(dir.filePath(fileName)); - if(!f.open(QIODevice::ReadOnly)) return QByteArray(); + if (!f.open(QIODevice::ReadOnly)) return QByteArray(); data = f.readAll(); f.close(); @@ -316,26 +336,26 @@ list.append("*"); list = dir.entryList(list, QDir::Files | QDir::NoSymLinks); - if(observer) observer->setObserverMaximum(list.size()); + if (observer) observer->setObserverMaximum(list.size()); // QTime t;t.start(); int i=0; - foreach(const QString &name, list) { - if(observer) { - if(observer->observerWasCanceled()) { + for (const QString &name : qAsConst(list)) { + if (observer) { + if (observer->observerWasCanceled()) { return Aborted; } observer->setObserverValue(i++); } - if(name.compare("maplist", Qt::CaseInsensitive) == 0) { - if(!Data::openMaplist(fileData2(name))) { + if (name.compare("maplist", Qt::CaseInsensitive) == 0) { + if (!Data::openMaplist(fileData2(name))) { qWarning() << "Cannot open maplist!"; } - } else if(name.endsWith(".tut", Qt::CaseInsensitive)) { + } else if (name.endsWith(".tut", Qt::CaseInsensitive)) { fieldArchive()->addTut(name.toLower().left(name.size()-4)); - } else if(!name.contains(".")) { + } else if (!name.contains(".")) { fieldArchive()->appendField(new FieldPC(name, this)); } } @@ -349,47 +369,53 @@ { bool saveAs; - if(!path.isEmpty()) { + if (!path.isEmpty()) { saveAs = QDir::cleanPath(path) != QDir::cleanPath(dir.path()); } else { saveAs = false; } - quint32 nbFiles = fieldArchive()->size(); - if(observer) observer->setObserverMaximum(nbFiles); + int i = 0; + FieldArchiveIterator it(*(fieldArchive())); - for(quint32 fieldID=0 ; fieldIDobserverWasCanceled()) { + if (observer) { + observer->setObserverMaximum(fieldArchive()->size()); + } + + while (it.hasNext()) { + if (observer && observer->observerWasCanceled()) { return Aborted; } - Field *field = fieldArchive()->field(fieldID, false); - if(field) { + Field *field = it.next(false); + if (field) { QString fileName = field->name(), filePath = dir.filePath(fileName); - if(field->isOpen() && field->isModified()) { + if (field->isOpen() && field->isModified()) { qint8 err = field->save(filePath, true); - if(err == 2) return ErrorOpening; - if(err == 1) return Invalid; - if(err != 0) return NotImplemented; - } else if(saveAs) { + if (err == 2) return ErrorOpening; + if (err == 1) return Invalid; + if (err != 0) return NotImplemented; + } else if (saveAs) { QString dstPath = path + "/" + fileName; - if(!QFile::copy(filePath, dstPath)) { + if (!QFile::copy(filePath, dstPath)) { return ErrorCopying; } } } - if(observer) observer->setObserverValue(fieldID); + if (observer) { + observer->setObserverValue(i++); + } } QMapIterator itTut(fieldArchive()->tuts()); - while(itTut.hasNext()) { + while (itTut.hasNext()) { itTut.next(); TutFile *tut = itTut.value(); - if(tut != NULL && tut->isModified()) { + if (tut != nullptr && tut->isModified()) { QFile tutFile(dir.filePath(itTut.key() + ".tut")); - if(tutFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + if (tutFile.open(QIODevice::WriteOnly | QIODevice::Truncate)) { tutFile.write(tut->save()); tutFile.close(); } else { diff -Nru makoureactor-1.7.2/core/field/FieldArchiveIOPC.h makoureactor-1.8.0/core/field/FieldArchiveIOPC.h --- makoureactor-1.7.2/core/field/FieldArchiveIOPC.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldArchiveIOPC.h 2020-08-08 18:46:56.000000000 +0000 @@ -60,6 +60,9 @@ bool observerWasCanceled() const { return observer && observer->observerWasCanceled(); } + bool observerRetry(const QString &message) { + return observer && observer->observerRetry(message); + } private: QByteArray fieldData2(Field *field, const QString &extension, bool unlzs); QByteArray fileData2(const QString &fileName); diff -Nru makoureactor-1.7.2/core/field/FieldArchiveIOPS.cpp makoureactor-1.8.0/core/field/FieldArchiveIOPS.cpp --- makoureactor-1.7.2/core/field/FieldArchiveIOPS.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldArchiveIOPS.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -35,14 +35,14 @@ QByteArray FieldArchiveIOPS::mimData(Field *field, bool unlzs) { // use data from the cache - if(unlzs && mimDataIsCached(field)) { + if (unlzs && mimDataIsCached(field)) { return mimDataCache; } QByteArray data = mimData2(field, unlzs); // put decompressed data in the cache - if(unlzs && !data.isEmpty()) { + if (unlzs && !data.isEmpty()) { mimCache = field; mimDataCache = data; } @@ -52,14 +52,14 @@ QByteArray FieldArchiveIOPS::modelData(Field *field, bool unlzs) { // use data from the cache - if(unlzs && modelDataIsCached(field)) { + if (unlzs && modelDataIsCached(field)) { return modelDataCache; } QByteArray data = modelData2(field, unlzs); // put decompressed data in the cache - if(unlzs && !data.isEmpty()) { + if (unlzs && !data.isEmpty()) { modelCache = field; modelDataCache = data; } @@ -102,34 +102,47 @@ Archive *FieldArchiveIOPSFile::device() { - return NULL; + return nullptr; } QByteArray FieldArchiveIOPSFile::fieldData2(Field *field, const QString &extension, bool unlzs) { Q_UNUSED(field) - Q_UNUSED(extension) - return fileData(QString(), unlzs); + QString path; + + if (extension != "DAT") { + path = fic.fileName().left(fic.fileName().lastIndexOf('.')) + "." + extension; + } + + return fileData(path, unlzs); } QByteArray FieldArchiveIOPSFile::mimData2(Field *field, bool unlzs) { Q_UNUSED(field) - Q_UNUSED(unlzs) - return QByteArray(); + return fileData(fic.fileName().left(fic.fileName().lastIndexOf('.')) + ".MIM", unlzs); } QByteArray FieldArchiveIOPSFile::modelData2(Field *field, bool unlzs) { Q_UNUSED(field) - Q_UNUSED(unlzs) - return QByteArray(); + return fileData(fic.fileName().left(fic.fileName().lastIndexOf('.')) + ".BSX", unlzs); } QByteArray FieldArchiveIOPSFile::fileData2(const QString &fileName) { - Q_UNUSED(fileName) - if(!fic.isOpen() && !fic.open(QIODevice::ReadOnly)) return QByteArray(); + if (!fileName.isEmpty() && fileName != fic.fileName()) { + QFile f(fileName); + if (!f.open(QIODevice::ReadOnly)) { + return QByteArray(); + } + QByteArray d = f.readAll(); + f.close(); + + return d; + } + + if (!fic.isOpen() && !fic.open(QIODevice::ReadOnly)) return QByteArray(); fic.reset(); QByteArray data = fic.readAll(); fic.close(); @@ -150,7 +163,9 @@ QString name = this->name(); fieldArchive()->appendField(new FieldPS(name.left(name.lastIndexOf('.')), this)); - Field *field = fieldArchive()->field(0); + // Open field + FieldArchiveIterator it(*(fieldArchive())); + Field *field = it.next(); return field && field->isOpen() ? Ok : Invalid; } @@ -160,12 +175,18 @@ Q_UNUSED(observer) QString path = path0.isNull() ? fic.fileName() : path0; - Field *field = fieldArchive()->field(0, false); - if(field && field->isOpen() && field->isModified()) { + FieldArchiveIterator it(*(fieldArchive())); + + if (!it.hasNext()) { + return FieldNotFound; + } + + Field *field = it.next(false); + if (field && field->isOpen() && field->isModified()) { qint8 err = field->save(path, true); - if(err == 2) return ErrorOpening; - if(err == 1) return Invalid; - if(err != 0) return NotImplemented; + if (err == 2) return ErrorOpening; + if (err == 1) return Invalid; + if (err != 0) return NotImplemented; } return Ok; @@ -183,7 +204,7 @@ Archive *FieldArchiveIOPSIso::device() { - return NULL; + return nullptr; } QByteArray FieldArchiveIOPSIso::fieldData2(Field *field, const QString &extension, bool unlzs) @@ -206,9 +227,9 @@ QByteArray FieldArchiveIOPSIso::fileData2(const QString &fileName) { - if(isoFieldDirectory) { + if (isoFieldDirectory) { IsoFile *file = isoFieldDirectory->file(fileName.toUpper()); - if(file) { + if (file) { return file->data(); } } @@ -217,12 +238,12 @@ FieldArchiveIO::ErrorCode FieldArchiveIOPSIso::openIso() { - if(!iso.isOpen() && !iso.open(QIODevice::ReadOnly)) { + if (!iso.isOpen() && !iso.open(QIODevice::ReadOnly)) { return ErrorOpening; } isoFieldDirectory = iso.fieldDirectory(); - if(isoFieldDirectory == NULL) { + if (isoFieldDirectory == nullptr) { return FieldNotFound; } @@ -236,28 +257,31 @@ return error; } + + iso.maplist(); + QList files = isoFieldDirectory->files(); - if(observer) observer->setObserverMaximum(files.size()); + if (observer) observer->setObserverMaximum(files.size()); bool isDemo = iso.isDemo(); // QTime t;t.start(); int i=0; - foreach(IsoFile *file, files) { - if(observer) { - if(observer->observerWasCanceled()) { + for (IsoFile *file : qAsConst(files)) { + if (observer) { + if (observer->observerWasCanceled()) { return Aborted; } observer->setObserverValue(i); } - if(isDemo) { - if(file->name().endsWith(".ATE")) { + if (isDemo) { + if (file->name().endsWith(".ATE")) { QString name = file->name().mid(file->name().lastIndexOf('/')+1); fieldArchive()->appendField(new FieldPSDemo(name.left(name.lastIndexOf('.')), this)); } - } else if(file->name().endsWith(".DAT") && !file->name().startsWith("WM")) { + } else if (file->name().endsWith(".DAT") && !file->name().startsWith("WM")) { QString name = file->name().mid(file->name().lastIndexOf('/')+1); fieldArchive()->appendField(new FieldPS(name.left(name.lastIndexOf('.')), this)); } @@ -266,7 +290,7 @@ Data::windowBin = WindowBinFile(); - if(!Data::windowBin.open(iso.windowBinData())) { + if (!Data::windowBin.open(iso.windowBinData())) { qWarning() << "Cannot open window.bin"; } @@ -283,24 +307,25 @@ bool saveAs = QFileInfo(path) != QFileInfo(iso.io()); - if(observer) observer->setObserverMaximum(100); + if (observer) observer->setObserverMaximum(100); // FIELD/*.DAT - for(int fieldID = 0 ; fieldID < fieldArchive()->size() ; ++fieldID) { - if(observer && observer->observerWasCanceled()) { + FieldArchiveIterator it(*(fieldArchive())); + while (it.hasNext()) { + if (observer && observer->observerWasCanceled()) { return Aborted; } - Field *field = fieldArchive()->field(fieldID, false); - if(field && field->isOpen() && field->isModified()) { + Field *field = it.next(false); + if (field && field->isOpen() && field->isModified()) { IsoFile *isoField = isoFieldDirectory->file(field->name().toUpper() + ".DAT"); - if(isoField == NULL) { + if (isoField == nullptr) { continue; } QByteArray newData; - if(field->save(newData, true)) { + if (field->save(newData, true)) { isoField->setModifiedFile(newData); } else { return Invalid; @@ -309,12 +334,12 @@ } IsoArchive isoTemp(path % ".makoutemp"); - if(!isoTemp.open(QIODevice::ReadWrite | QIODevice::Truncate)) { + if (!isoTemp.open(QIODevice::ReadWrite | QIODevice::Truncate)) { return ErrorOpening; } - if(!iso.pack(&isoTemp, observer, isoFieldDirectory)) { - if(observer && observer->observerWasCanceled()) { + if (!iso.pack(&isoTemp, observer, isoFieldDirectory)) { + if (observer && observer->observerWasCanceled()) { return Aborted; } return Invalid; @@ -325,20 +350,39 @@ iso.close(); isoTemp.close(); - // Remove or close the old file - if(!saveAs) { - if(!QFile::remove(iso.fileName())) { - return ErrorRemoving; - } - } else { + if (saveAs) { iso.setFileName(path); } // Move the temporary file - if(QFile::exists(path) && !QFile::remove(path)) { - return ErrorRemoving; + if (QFile::exists(path) && !QFile::remove(path)) { + bool removed = false; + + while (observer->observerRetry(QObject::tr("Cannot remove destination archive"))) { + if (QFile::remove(path)) { + removed = true; + break; + } + } + + if (!removed) { + QFile::remove(isoTemp.fileName()); + openIso(); // Reopen + return ErrorRemoving; + } } - if(!QFile::rename(isoTemp.fileName(), path)) { - return ErrorRenaming; + if (!QFile::rename(isoTemp.fileName(), path)) { + bool renamed = false; + + while (observer->observerRetry(QObject::tr("Cannot rename temporary file to destination path"))) { + if (QFile::rename(isoTemp.fileName(), path)) { + renamed = true; + break; + } + } + + if (!renamed) { + return ErrorRenaming; + } } ErrorCode error = openIso(); @@ -361,7 +405,7 @@ Archive *FieldArchiveIOPSDir::device() { - return NULL; + return nullptr; } QByteArray FieldArchiveIOPSDir::fieldData2(Field *field, const QString &extension, bool unlzs) @@ -387,7 +431,7 @@ QByteArray data; QFile f(dir.filePath(fileName.toUpper())); - if(!f.open(QIODevice::ReadOnly)) return QByteArray(); + if (!f.open(QIODevice::ReadOnly)) return QByteArray(); data = f.readAll(); f.close(); @@ -400,20 +444,20 @@ list.append("*.DAT"); list = dir.entryList(list, QDir::Files | QDir::NoSymLinks); - if(observer) observer->setObserverMaximum(list.size()); + if (observer) observer->setObserverMaximum(list.size()); // QTime t;t.start(); int i=0; - foreach(const QString &name, list) { - if(observer) { - if(observer->observerWasCanceled()) { + for (const QString &name : qAsConst(list)) { + if (observer) { + if (observer->observerWasCanceled()) { return Aborted; } observer->setObserverValue(i++); } - if(!name.startsWith("WM", Qt::CaseInsensitive)) { + if (!name.startsWith("WM", Qt::CaseInsensitive)) { fieldArchive()->appendField(new FieldPS(name.left(name.lastIndexOf('.')), this)); } } @@ -427,36 +471,42 @@ { bool saveAs; - if(!path.isEmpty()) { + if (!path.isEmpty()) { saveAs = QDir::cleanPath(path) != QDir::cleanPath(dir.path()); } else { saveAs = false; } - quint32 nbFiles = fieldArchive()->size(); - if(observer) observer->setObserverMaximum(nbFiles); + FieldArchiveIterator it(*(fieldArchive())); + quint32 i = 0; - for(quint32 fieldID=0 ; fieldIDobserverWasCanceled()) { + if (observer) { + observer->setObserverMaximum(fieldArchive()->size()); + } + + while (it.hasNext()) { + if (observer && observer->observerWasCanceled()) { return Aborted; } - Field *field = fieldArchive()->field(fieldID, false); + Field *field = it.next(false); QString datName = field->name().toUpper() + ".DAT", datPath = dir.filePath(datName); - if(field) { - if(field->isOpen() && field->isModified()) { + if (field) { + if (field->isOpen() && field->isModified()) { qint8 err = field->save(datPath, true); - if(err == 2) return ErrorOpening; - if(err == 1) return Invalid; - if(err != 0) return NotImplemented; - } else if(saveAs) { + if (err == 2) return ErrorOpening; + if (err == 1) return Invalid; + if (err != 0) return NotImplemented; + } else if (saveAs) { QString dstPath = path + "/" + datName; - if(!QFile::copy(datPath, dstPath)) { + if (!QFile::copy(datPath, dstPath)) { return ErrorCopying; } } } - if(observer) observer->setObserverValue(fieldID); + if (observer) { + observer->setObserverValue(i++); + } } return Ok; diff -Nru makoureactor-1.7.2/core/field/FieldArchivePC.cpp makoureactor-1.8.0/core/field/FieldArchivePC.cpp --- makoureactor-1.7.2/core/field/FieldArchivePC.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldArchivePC.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -16,6 +16,7 @@ ** along with this program. If not, see . ****************************************************************************/ #include "FieldArchivePC.h" +#include "BackgroundFilePC.h" FieldArchivePC::FieldArchivePC() : FieldArchive() @@ -25,7 +26,7 @@ FieldArchivePC::FieldArchivePC(const QString &path, FieldArchiveIO::Type type) : FieldArchive() { - switch(type) { + switch (type) { case FieldArchiveIO::Lgp: setIO(new FieldArchiveIOPCLgp(path, this)); break; @@ -42,15 +43,19 @@ FieldArchivePC::~FieldArchivePC() { - foreach(TutFile *tut, _tuts) { - if(tut != NULL) delete tut; + for (TutFile *tut : qAsConst(_tuts)) { + if (tut != nullptr) { + delete tut; + } } } void FieldArchivePC::clear() { - foreach(TutFile *tut, _tuts) { - if(tut != NULL) delete tut; + for (TutFile *tut : qAsConst(_tuts)) { + if (tut != nullptr) { + delete tut; + } } _tuts.clear(); @@ -72,25 +77,25 @@ { QMapIterator it(_tuts); - while(it.hasNext()) { + while (it.hasNext()) { it.next(); const QString &tutName = it.key(); - if(name.startsWith(tutName, Qt::CaseInsensitive)) { + if (name.startsWith(tutName, Qt::CaseInsensitive)) { TutFilePC *tutFile = it.value(); - if(tutFile == NULL) { + if (tutFile == nullptr) { QByteArray data = io()->fileData(tutName + ".tut", false, false); - if(!data.isEmpty()) { + if (!data.isEmpty()) { tutFile = new TutFilePC(); - if(!static_cast(tutFile)->open(data)) { + if (!static_cast(tutFile)->open(data)) { delete tutFile; - return NULL; + return nullptr; } _tuts.insert(tutName, tutFile); return tutFile; } else { - return NULL; + return nullptr; } } else { return tutFile; @@ -98,7 +103,7 @@ } } - return NULL; + return nullptr; } const QMap &FieldArchivePC::tuts() const @@ -108,13 +113,13 @@ void FieldArchivePC::addTut(const QString &name) { - _tuts.insert(name, NULL); + _tuts.insert(name, nullptr); } void FieldArchivePC::setSaved() { - foreach(TutFile *tut, _tuts) { - if(tut != NULL) { + for (TutFile *tut : qAsConst(_tuts)) { + if (tut != nullptr) { tut->setModified(false); } } @@ -129,39 +134,67 @@ void FieldArchivePC::cleanModelLoader() { + FieldArchiveIterator it(*this); + int i = 0; + observer()->setObserverMaximum(size()); - for(int fieldID=0 ; fieldIDobserverWasCanceled()) { + while (it.hasNext()) { + if (observer()->observerWasCanceled()) { return; } - FieldPC *field = this->field(fieldID, true); - if(field != NULL) { + FieldPC *field = static_cast(it.next()); + if (field != nullptr) { FieldModelLoaderPC *modelLoader = field->fieldModelLoader(); - if(modelLoader->isOpen()) { + if (modelLoader->isOpen()) { modelLoader->clean(); - if(modelLoader->isModified() && !field->isModified()) { + if (modelLoader->isModified() && !field->isModified()) { field->setModified(true); } } } - observer()->setObserverValue(fieldID); + observer()->setObserverValue(i++); } } void FieldArchivePC::removeUnusedSections() { + FieldArchiveIterator it(*this); + int i = 0; + observer()->setObserverMaximum(size()); - for(int fieldID=0 ; fieldIDobserverWasCanceled()) { + while (it.hasNext()) { + if (observer()->observerWasCanceled()) { return; } - FieldPC *field = this->field(fieldID, true); - if(field != NULL) { + FieldPC *field = static_cast(it.next()); + if (field != nullptr) { field->setRemoveUnusedSection(true); field->setModified(true); } - observer()->setObserverValue(fieldID); + observer()->setObserverValue(i++); + } +} + +void FieldArchivePC::repairBackgroundsPC() +{ + FieldArchiveIterator it(*this); + int i = 0; + + observer()->setObserverMaximum(size()); + + while (it.hasNext()) { + if (observer()->observerWasCanceled()) { + return; + } + FieldPC *field = static_cast(it.next()); + if (field != nullptr && (field->name().toLower() == "lastmap" || field->name().toLower() == "fr_e")) { + BackgroundFilePC *bg = static_cast(field->background()); + if (bg->isOpen() && bg->repair()) { + field->setModified(true); + } + } + observer()->setObserverValue(i++); } } diff -Nru makoureactor-1.7.2/core/field/FieldArchivePC.h makoureactor-1.8.0/core/field/FieldArchivePC.h --- makoureactor-1.7.2/core/field/FieldArchivePC.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldArchivePC.h 2020-08-08 18:46:56.000000000 +0000 @@ -46,6 +46,7 @@ void cleanModelLoader(); void removeUnusedSections(); + void repairBackgroundsPC(); private: QMap _tuts; }; diff -Nru makoureactor-1.7.2/core/field/FieldArchivePS.cpp makoureactor-1.8.0/core/field/FieldArchivePS.cpp --- makoureactor-1.7.2/core/field/FieldArchivePS.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldArchivePS.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -25,7 +25,7 @@ FieldArchivePS::FieldArchivePS(const QString &path, FieldArchiveIO::Type type) : FieldArchive() { - switch(type) { + switch (type) { case FieldArchiveIO::Dir: setIO(new FieldArchiveIOPSDir(path, this)); break; diff -Nru makoureactor-1.7.2/core/field/Field.cpp makoureactor-1.8.0/core/field/Field.cpp --- makoureactor-1.7.2/core/field/Field.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/Field.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -29,52 +29,52 @@ { } -Field::~Field() +Field::Field(const QString &name) : + Field(name, nullptr) { - foreach(FieldPart *part, _parts) { - if(part) delete part; - } -} -bool Field::isOpen() const -{ - return _isOpen; } -bool Field::isModified() const +Field::~Field() { - return _isModified; + for (FieldPart *part : qAsConst(_parts)) { + if (part) delete part; + } } void Field::setModified(bool modified) { - if(!_isOpen) { - if(!open()) { + if (!_isOpen && _io != nullptr) { + if (!open()) { qWarning() << "Unable to reopen!"; return; } } _isModified = modified; FieldPart *section1 = part(Scripts); - if(section1) section1->setModified(modified); + if (section1) section1->setModified(modified); } bool Field::open(bool dontOptimize) { QByteArray fileData; - if(headerSize() > 0) { + if (_io == nullptr) { + return false; + } + + if (headerSize() > 0) { QString fileType = sectionFile(Scripts); - if(!dontOptimize && !_io->fieldDataIsCached(this, fileType)) { + if (!dontOptimize && !_io->fieldDataIsCached(this, fileType)) { QByteArray lzsData = _io->fieldData(this, fileType, false); - if(lzsData.size() < 4) return false; + if (lzsData.size() < 4) return false; const char *lzsDataConst = lzsData.constData(); quint32 lzsSize; memcpy(&lzsSize, lzsDataConst, 4); - if(!Config::value("lzsNotCheck").toBool() && (quint32)lzsData.size() != lzsSize + 4) + if (!Config::value("lzsNotCheck").toBool() && (quint32)lzsData.size() != lzsSize + 4) return false; fileData = LZS::decompress(lzsDataConst + 4, qMin(lzsSize, quint32(lzsData.size() - 4)), headerSize());//partial decompression @@ -82,7 +82,7 @@ fileData = _io->fieldData(this, fileType); } - if(fileData.size() < headerSize()) return false; + if (fileData.size() < headerSize()) return false; openHeader(fileData); } @@ -98,7 +98,7 @@ qint8 ret = importer(path, isDat, compressed, Field::FieldSection(0xFFFF), // Everything device2); - if(ret == 0) { + if (ret == 0) { _isOpen = true; } return ret; @@ -109,7 +109,7 @@ qint8 ret = importer(data, isPSField, Field::FieldSection(0xFFFF), // Everything device2); - if(ret == 0) { + if (ret == 0) { _isOpen = true; } return ret; @@ -119,7 +119,7 @@ { int idPart = sectionId(part); - if(idPart < sectionCount() - 1) { + if (idPart < sectionCount() - 1) { return sectionPosition(idPart+1) - paddingBetweenSections() - sectionPosition(idPart); } return -1; @@ -127,28 +127,30 @@ QByteArray Field::sectionData(FieldSection part, bool dontOptimize) { - if(!_isOpen) { + if (!_isOpen) { open(); } - if(!_isOpen) return QByteArray(); + if (!_isOpen || _io == nullptr) { + return QByteArray(); + } int idPart = sectionId(part), position = sectionPosition(idPart), size = sectionSize(part); QString fileType = sectionFile(part); - if(size < 0) { + if (size < 0) { dontOptimize = true; } QByteArray data; - if(dontOptimize || _io->fieldDataIsCached(this, fileType)) { + if (dontOptimize || _io->fieldDataIsCached(this, fileType)) { data = _io->fieldData(this, fileType); } else { QByteArray lzsData = _io->fieldData(this, fileType, false); - if(lzsData.size() < 4) { + if (lzsData.size() < 4) { return QByteArray(); } @@ -156,14 +158,14 @@ quint32 lzsSize; memcpy(&lzsSize, lzsDataConst, 4); - if(!Config::value("lzsNotCheck").toBool() && (quint32)lzsData.size() != lzsSize + 4) { + if (!Config::value("lzsNotCheck").toBool() && (quint32)lzsData.size() != lzsSize + 4) { return QByteArray(); } data = LZS::decompress(lzsDataConst + 4, qMin(lzsSize, quint32(lzsData.size() - 4)), sectionPosition(idPart+1)); } - if(size < 0) { + if (size < 0) { QByteArray footer = saveFooter(); if (!footer.isEmpty() && data.right(footer.size()) == footer) { return data.mid(position, data.size() - position - footer.size()); @@ -172,14 +174,9 @@ return data.mid(position, size); } -FieldArchiveIO *Field::io() const -{ - return _io; -} - FieldPart *Field::createPart(FieldSection section) { - switch(section) { + switch (section) { case Scripts: return new Section1File(this); case Akaos: return new TutFileStandard(this); case Camera: return new CaFile(this); @@ -187,6 +184,7 @@ case Walkmesh: return new IdFile(this); case Encounter: return new EncounterFile(this); case Inf: return new InfFile(this); + case Tiles: return new BackgroundTilesFile(this); default: return 0; } } @@ -200,18 +198,42 @@ { FieldPart *p = part(section); - if(!p) { + if (!p) { p = createPart(section); _parts.insert(section, p); } - if(open && !p->isOpen()) { + if (open && !p->isOpen()) { p->open(); } return p; } +void Field::initEmpty() +{ + for (const FieldSection §ion : orderOfSections() << Akaos) { + FieldPart *p = part(section); + + if (!p) { + p = createPart(section); + if (p) { + _parts.insert(section, p); + } + } + + if (p) { + p->initEmpty(); + p->setOpen(true); + p->setModified(true); + } + } + + setRemoveUnusedSection(true); + _isOpen = true; + setModified(true); +} + Section1File *Field::scriptsAndTexts(bool open) { return static_cast(part(Scripts, open)); @@ -224,9 +246,7 @@ TutFileStandard *Field::tutosAndSounds(bool open) { - TutFileStandard *tut = static_cast(part(Akaos, open)); - scriptsAndTexts(false)->setTut(tut); - return tut; + return static_cast(part(Akaos, open)); } IdFile *Field::walkmesh(bool open) @@ -249,6 +269,11 @@ return static_cast(part(ModelLoader, open)); } +BackgroundTilesFile *Field::tiles(bool open) +{ + return static_cast(part(Tiles, open)); +} + BackgroundFile *Field::background(bool open) { return static_cast(part(Background, open)); @@ -259,18 +284,13 @@ QMap ret; int modelCount = scriptsAndTexts()->modelCount(); - for(int modelId=0 ; modelId < modelCount ; ++modelId) { + for (int modelId=0; modelId < modelCount; ++modelId) { ret.insert(modelId, fieldModel(modelId, 0, animate, open)); } return ret; } -const QString &Field::name() const -{ - return _name; -} - void Field::setName(const QString &name) { _name = name; @@ -279,8 +299,10 @@ void Field::setSaved() { - _isOpen = false; // Force reopen to refresh positions automatically - foreach(FieldPart *part, _parts) { + if (_io != nullptr) { + _isOpen = false; // Force reopen to refresh positions automatically + } + for (FieldPart *part : qAsConst(_parts)) { part->setModified(false); } } @@ -289,7 +311,7 @@ { newData = QByteArray(); - if(!isOpen()) { + if (!isOpen()) { return false; } @@ -300,33 +322,37 @@ // Sections int id=0; - foreach(const FieldSection &fieldSection, orderOfSections()) { + for (const FieldSection &fieldSection : orderOfSections()) { // Section position quint32 pos = headerSize() + newData.size() + diffSectionPos(); toc.append((char *)&pos, 4); QByteArray section; - if(fieldSection != Unused || !_removeUnusedSection) { // FIXME: ugly hack only for PC version + if (fieldSection != Tiles || !_removeUnusedSection) { // FIXME: ugly hack only for PC version // Section data FieldPart *fieldPart = part(fieldSection == Field::PalettePC ? Field::Background // FIXME: EXCEPTION NEEDS TO BE REMOVED IN THE FUTURE : fieldSection); - if(fieldPart && fieldPart->canSave() && + if (fieldPart && fieldPart->canSave() && fieldPart->isOpen() && fieldPart->isModified()) { - if(fieldSection == Field::PalettePC) { // FIXME: EXCEPTION NEEDS TO BE REMOVED IN THE FUTURE + if (fieldSection == Field::PalettePC) { // FIXME: EXCEPTION NEEDS TO BE REMOVED IN THE FUTURE section = static_cast(fieldPart)->savePal(); } else { section = fieldPart->save(); + if (section.isEmpty()) { + qWarning() << "Field::save empty section error" << int(fieldSection); + return false; + } } } else { section = sectionData(fieldSection, true); } } - if(hasSectionHeader()) { + if (hasSectionHeader()) { quint32 section_size = section.size(); newData.append((char *)§ion_size, 4); } @@ -346,7 +372,7 @@ // Header prepended to the section data newData.prepend(toc); - if(compress) { + if (compress) { const QByteArray &compresse = LZS::compress(newData); quint32 lzsSize = compresse.size(); newData = QByteArray((char *)&lzsSize, 4).append(compresse); @@ -359,9 +385,9 @@ { QByteArray newData; - if(save(newData, compress)) { + if (save(newData, compress)) { QFile fic(path); - if(!fic.open(QIODevice::WriteOnly | QIODevice::Truncate)) { + if (!fic.open(QIODevice::WriteOnly | QIODevice::Truncate)) { return 2; } fic.write(newData); @@ -373,108 +399,114 @@ return 0; } -qint8 Field::importer(const QString &path, bool isDat, bool compressed, FieldSections part, QIODevice *device2) +qint8 Field::importer(const QString &path, bool isDat, bool compressed, FieldSections part, QIODevice *bsxDevice, + QIODevice *mimDevice) { QFile fic(path); - if(!fic.open(QIODevice::ReadOnly)) return 1; - if(fic.size() > 10000000) return 2; + if (!fic.open(QIODevice::ReadOnly)) return 1; + if (fic.size() > 10000000) return 2; QByteArray data; - if(compressed) { // compressed field + if (compressed) { // compressed field quint32 fileSize=0; - if(fic.read((char *)&fileSize, 4) != 4) return 2; - if(fileSize+4 != fic.size()) return 2; + if (fic.read((char *)&fileSize, 4) != 4) return 2; + if (fileSize+4 != fic.size()) return 2; data = LZS::decompressAll(fic.readAll()); } else { // uncompressed field data = fic.readAll(); } - return importer(data, isDat, part, device2); + return importer(data, isDat, part, bsxDevice, mimDevice); } -qint8 Field::importer(const QByteArray &data, bool isPSField, FieldSections part, QIODevice *device2) +bool Field::importModelLoader(const QByteArray §ionData, bool isPSField, QIODevice *bsxDevice) { - if(isPSField) { + Q_UNUSED(sectionData); + Q_UNUSED(isPSField); + Q_UNUSED(bsxDevice); + return false; +} + +qint8 Field::importer(const QByteArray &data, bool isPSField, FieldSections part, QIODevice *bsxDevice, + QIODevice *mimDevice) +{ + if (isPSField) { quint32 sectionPositions[7]; const int headerSize = 28; - if(data.size() < headerSize) return 2; + if (data.size() < headerSize) return 2; memcpy(sectionPositions, data.constData(), headerSize); // header qint32 vramDiff = sectionPositions[0] - headerSize;// vram section1 pos - real section 1 pos - for(int i=0 ; i<7 ; ++i) { + for (int i=0; i<7; ++i) { sectionPositions[i] -= vramDiff; } - if(part.testFlag(Scripts)) { + if (part.testFlag(Scripts)) { Section1File *section1 = scriptsAndTexts(false); - if(!section1->open(data.mid(sectionPositions[0], sectionPositions[1]-sectionPositions[0]))) return 2; + if (!section1->open(data.mid(sectionPositions[0], sectionPositions[1]-sectionPositions[0]))) return 2; section1->setModified(true); } - if(part.testFlag(Akaos)) { + if (part.testFlag(Akaos)) { TutFile *_tut = tutosAndSounds(false); - if(!_tut->open(data.mid(sectionPositions[0], sectionPositions[1]-sectionPositions[0]))) return 2; + if (!_tut->open(data.mid(sectionPositions[0], sectionPositions[1]-sectionPositions[0]))) return 2; _tut->setModified(true); } - if(part.testFlag(Encounter)) { + if (part.testFlag(Encounter)) { EncounterFile *enc = encounter(false); - if(!enc->open(data.mid(sectionPositions[5], sectionPositions[6]-sectionPositions[5]))) return 2; + if (!enc->open(data.mid(sectionPositions[5], sectionPositions[6]-sectionPositions[5]))) return 2; enc->setModified(true); } - if(part.testFlag(Walkmesh)) { + if (part.testFlag(Walkmesh)) { IdFile *walk = walkmesh(false); - if(!walk->open(data.mid(sectionPositions[1], sectionPositions[2]-sectionPositions[1]))) return 2; + if (!walk->open(data.mid(sectionPositions[1], sectionPositions[2]-sectionPositions[1]))) return 2; walk->setModified(true); } - if(part.testFlag(Camera)) { + if (part.testFlag(Camera)) { CaFile *ca = camera(false); - if(!ca->open(data.mid(sectionPositions[3], sectionPositions[4]-sectionPositions[3]))) return 2; + if (!ca->open(data.mid(sectionPositions[3], sectionPositions[4]-sectionPositions[3]))) return 2; ca->setModified(true); } - if(part.testFlag(Inf)) { + if (part.testFlag(Inf)) { InfFile *inf = this->inf(false); - if(!inf->open(data.mid(sectionPositions[4], sectionPositions[5]-sectionPositions[4]))) return 2; + if (!inf->open(data.mid(sectionPositions[4], sectionPositions[5]-sectionPositions[4]))) return 2; + inf->setMapName(name()); inf->setModified(true); } - if(part.testFlag(Background)) { - if(!device2) { - qWarning() << "Field::importer Additional device need to be initialized"; + if (part.testFlag(ModelLoader)) { + if (!importModelLoader(data.mid(sectionPositions[6]), isPSField, bsxDevice)) { return 2; } - if(!device2->open(QIODevice::ReadOnly)) { - return 1; - } - - quint32 lzsSize; - - if(device2->read((char *)&lzsSize, 4) != 4) { + } + if (part.testFlag(Background)) { + if (!mimDevice) { + qWarning() << "Field::importer Additional device need to be initialized"; return 2; } - - if(lzsSize + 4 != device2->size()) { - return 2; + if (!mimDevice->open(QIODevice::ReadOnly)) { + return 1; } - QByteArray mimData = LZS::decompressAll(device2->readAll()), + QByteArray mimData = LZS::decompressAllWithHeader(mimDevice->readAll()), tilesData = data.mid(sectionPositions[2], sectionPositions[3]-sectionPositions[2]); BackgroundFilePS *bg; - if(isPS()) { + if (isPS()) { bg = static_cast(background(false)); } else { bg = new BackgroundFilePS(0); } - if(!bg->open(mimData, tilesData)) { - if(isPC()) { + if (!bg->open(mimData, tilesData)) { + if (isPC()) { delete bg; } return 2; } - if(isPC()) { + if (isPC()) { _parts.insert(Background, new BackgroundFilePC(bg->toPC(static_cast(this)))); delete bg; } @@ -484,58 +516,65 @@ } else { quint32 sectionPositions[9]; - if(data.size() < 6 + 9 * 4) return 3; + if (data.size() < 6 + 9 * 4) return 3; memcpy(sectionPositions, data.constData() + 6, 9 * 4); // header - if(part.testFlag(Scripts)) { + if (part.testFlag(Scripts)) { Section1File *section1 = scriptsAndTexts(false); - if(!section1->open(data.mid(sectionPositions[0]+4, sectionPositions[1]-sectionPositions[0]-4))) return 2; + if (!section1->open(data.mid(sectionPositions[0]+4, sectionPositions[1]-sectionPositions[0]-4))) return 2; section1->setModified(true); } - if(part.testFlag(Akaos)) { + if (part.testFlag(Akaos)) { TutFile *_tut = tutosAndSounds(false); - if(!_tut->open(data.mid(sectionPositions[0]+4, sectionPositions[1]-sectionPositions[0]-4))) return 2; + if (!_tut->open(data.mid(sectionPositions[0]+4, sectionPositions[1]-sectionPositions[0]-4))) return 2; _tut->setModified(true); } - if(part.testFlag(Encounter)) { + if (part.testFlag(ModelLoader)) { + if (!importModelLoader(data.mid(sectionPositions[1]+4, sectionPositions[2]-sectionPositions[1]-4), + isPSField, bsxDevice)) { + return 2; + } + } + if (part.testFlag(Encounter)) { EncounterFile *enc = encounter(false); - if(!enc->open(data.mid(sectionPositions[6]+4, sectionPositions[7]-sectionPositions[6]-4))) return 2; + if (!enc->open(data.mid(sectionPositions[6]+4, sectionPositions[7]-sectionPositions[6]-4))) return 2; enc->setModified(true); } - if(part.testFlag(Walkmesh)) { + if (part.testFlag(Walkmesh)) { IdFile *walk = walkmesh(false); - if(!walk->open(data.mid(sectionPositions[4]+4, sectionPositions[5]-sectionPositions[4]-4))) return 2; + if (!walk->open(data.mid(sectionPositions[4]+4, sectionPositions[5]-sectionPositions[4]-4))) return 2; walk->setModified(true); } - if(part.testFlag(Camera)) { + if (part.testFlag(Camera)) { CaFile *ca = camera(false); - if(!ca->open(data.mid(sectionPositions[1]+4, sectionPositions[2]-sectionPositions[1]-4))) return 2; + if (!ca->open(data.mid(sectionPositions[1]+4, sectionPositions[2]-sectionPositions[1]-4))) return 2; ca->setModified(true); } - if(part.testFlag(Inf)) { + if (part.testFlag(Inf)) { InfFile *inf = this->inf(false); - if(!inf->open(data.mid(sectionPositions[7]+4, sectionPositions[8]-sectionPositions[7]-4))) return 2; + if (!inf->open(data.mid(sectionPositions[7]+4, sectionPositions[8]-sectionPositions[7]-4))) return 2; + inf->setMapName(name()); inf->setModified(true); } - if(part.testFlag(Background)) { + if (part.testFlag(Background)) { QByteArray mimData = data.mid(sectionPositions[8]+4), palData = data.mid(sectionPositions[3]+4, sectionPositions[4]-sectionPositions[3]-4); BackgroundFilePC *bg; - if(isPC()) { + if (isPC()) { bg = static_cast(background(false)); } else { bg = new BackgroundFilePC(0); } - if(!bg->open(mimData, palData)) { - if(isPS()) { + if (!bg->open(mimData, palData)) { + if (isPS()) { delete bg; } return 2; } - if(isPS()) { + if (isPS()) { _parts.insert(Background, new BackgroundFilePS(bg->toPS(static_cast(this)))); delete bg; } @@ -546,8 +585,3 @@ return 0; } - -void Field::setRemoveUnusedSection(bool remove) -{ - _removeUnusedSection = remove; -} diff -Nru makoureactor-1.7.2/core/field/Field.h makoureactor-1.8.0/core/field/Field.h --- makoureactor-1.7.2/core/field/Field.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/Field.h 2020-08-08 18:46:56.000000000 +0000 @@ -28,6 +28,7 @@ #include "FieldModelLoader.h" #include "FieldModelFile.h" #include "BackgroundFile.h" +#include "BackgroundTilesFile.h" class FieldArchiveIO; @@ -44,15 +45,20 @@ Inf = 0x40, Background = 0x80, PalettePC = 0x100, - Unused = 0x200 + Tiles = 0x200 }; Q_DECLARE_FLAGS(FieldSections, FieldSection) Field(const QString &name, FieldArchiveIO *io); + explicit Field(const QString &name); virtual ~Field(); - bool isOpen() const; - bool isModified() const; + inline bool isOpen() const { + return _isOpen; + } + inline bool isModified() const { + return _isModified; + } void setModified(bool modified); virtual bool isPC() const=0; @@ -63,11 +69,15 @@ qint8 open(const QString &path, bool isDat, bool compressed, QIODevice *device2=0); qint8 open(const QByteArray &data, bool isPSField, QIODevice *device2=0); + void initEmpty(); + void setSaved(); bool save(QByteArray &newData, bool compress); qint8 save(const QString &path, bool compress); - qint8 importer(const QString &path, bool isDat, bool compressed, FieldSections part, QIODevice *device2=0); - virtual qint8 importer(const QByteArray &data, bool isPSField, FieldSections part, QIODevice *device2=0); + qint8 importer(const QString &path, bool isDat, bool compressed, FieldSections part, QIODevice *bsxDevice = nullptr, + QIODevice *mimDevice = nullptr); + qint8 importer(const QByteArray &data, bool isPSField, FieldSections part, QIODevice *bsxDevice = nullptr, + QIODevice *mimDevice = nullptr); Section1File *scriptsAndTexts(bool open=true); EncounterFile *encounter(bool open=true); @@ -75,18 +85,25 @@ IdFile *walkmesh(bool open=true); CaFile *camera(bool open=true); InfFile *inf(bool open=true); + BackgroundTilesFile *tiles(bool open=true); BackgroundFile *background(bool open=true); virtual FieldModelLoader *fieldModelLoader(bool open=true); virtual FieldModelFile *fieldModel(int modelID, int animationID=0, bool animate=true, bool open=true)=0; QMap fieldModels(bool animate=true, bool open=true); - const QString &name() const; + inline const QString &name() const { + return _name; + } void setName(const QString &name); - virtual FieldArchiveIO *io() const; + inline virtual FieldArchiveIO *io() const { + return _io; + } int sectionSize(FieldSection part) const; QByteArray sectionData(FieldSection part, bool dontOptimize=false); - void setRemoveUnusedSection(bool remove);// FIXME: only in PC version, ugly hack detected! + inline void setRemoveUnusedSection(bool remove) { // FIXME: only in PC version, ugly hack detected! + _removeUnusedSection = remove; + } protected: virtual int headerSize() const=0; virtual void openHeader(const QByteArray &fileData)=0; @@ -103,6 +120,7 @@ virtual QList orderOfSections() const=0; virtual quint32 diffSectionPos() const=0; virtual bool hasSectionHeader() const=0; + virtual bool importModelLoader(const QByteArray §ionData, bool isPSField, QIODevice *bsxDevice); private: FieldPart *part(FieldSection section, bool open); diff -Nru makoureactor-1.7.2/core/field/FieldIO.cpp makoureactor-1.8.0/core/field/FieldIO.cpp --- makoureactor-1.7.2/core/field/FieldIO.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldIO.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -23,38 +23,47 @@ { } +bool FieldSaveIO::open(OpenMode mode) +{ + if (!setCache()) { + return false; + } + return QIODevice::open(mode); +} + void FieldSaveIO::close() { _cache.clear(); QIODevice::close(); } +qint64 FieldSaveIO::size() const +{ + return _cache.size(); +} + qint64 FieldSaveIO::readData(char *data, qint64 maxSize) { - if(setCache()) { - if(pos() < _cache.size()) { - const char *constData = _cache.constData(); - qint64 r = qMin(maxSize, _cache.size() - pos()); - if(r > 0) { - memcpy(data, constData + pos(), r); - return r; - } else if(r == 0) { - return 0; - } else { - return -1; - } - } else { + if (pos() < _cache.size()) { + const char *constData = _cache.constData(); + qint64 r = qMin(maxSize, _cache.size() - pos()); + if (r > 0) { + memcpy(data, constData + pos(), r); + return r; + } else if (r == 0) { return 0; } + return -1; } - return -1; + return 0; } bool FieldSaveIO::setCache() { - if(_cache.isEmpty()) { - if(!_field->save(_cache, true)) { + if (_cache.isEmpty()) { + if (!_field->save(_cache, true)) { _cache.clear(); + setErrorString(tr("Cannot save field map %1").arg(_field->name())); return false; } } diff -Nru makoureactor-1.7.2/core/field/FieldIO.h makoureactor-1.8.0/core/field/FieldIO.h --- makoureactor-1.7.2/core/field/FieldIO.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldIO.h 2020-08-08 18:46:56.000000000 +0000 @@ -26,7 +26,9 @@ { public: FieldSaveIO(Field *field, QObject *parent=0); + virtual bool open(OpenMode mode); virtual void close(); + virtual qint64 size() const; protected: virtual qint64 readData(char *data, qint64 maxSize); private: diff -Nru makoureactor-1.7.2/core/field/FieldModelFile.cpp makoureactor-1.8.0/core/field/FieldModelFile.cpp --- makoureactor-1.7.2/core/field/FieldModelFile.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldModelFile.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -23,14 +23,14 @@ FieldModelFile::~FieldModelFile() { - foreach (const FieldModelBone &bone, _skeleton.bones()) { + for (const FieldModelBone &bone : _skeleton.bones()) { qDeleteAll(bone.parts()); } } void FieldModelFile::clear() { - foreach (const FieldModelBone &bone, _skeleton.bones()) { + for (const FieldModelBone &bone : _skeleton.bones()) { qDeleteAll(bone.parts()); } _skeleton.clear(); @@ -39,5 +39,5 @@ bool FieldModelFile::isValid() const { - return !_animations.isEmpty() && !_skeleton.isEmpty(); + return _skeleton.boneCount() == 1 || (!_animations.isEmpty() && !_skeleton.isEmpty()); } diff -Nru makoureactor-1.7.2/core/field/FieldModelFile.h makoureactor-1.8.0/core/field/FieldModelFile.h --- makoureactor-1.7.2/core/field/FieldModelFile.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldModelFile.h 2020-08-08 18:46:56.000000000 +0000 @@ -58,6 +58,8 @@ return _animations.at(animationID); } virtual QImage loadedTexture(FieldModelGroup *group)=0; + virtual void *textureIdForGroup(FieldModelGroup *group) const=0; + virtual QHash loadedTextures()=0; private: Q_DISABLE_COPY(FieldModelFile) protected: diff -Nru makoureactor-1.7.2/core/field/FieldModelFilePC.cpp makoureactor-1.8.0/core/field/FieldModelFilePC.cpp --- makoureactor-1.7.2/core/field/FieldModelFilePC.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldModelFilePC.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -24,7 +24,7 @@ #include "../TexFile.h" FieldModelFilePC::FieldModelFilePC() : - FieldModelFile(), _charLgp(0) + FieldModelFile(), _charLgp(nullptr) { } @@ -34,14 +34,24 @@ FieldModelFile::clear(); } -quint8 FieldModelFilePC::load(const QString &hrc, const QString &a, bool animate) +void FieldModelFilePC::openTextures(const QStringList &textureFiles) { - if (hrc.isEmpty() || a.isEmpty()) { - return 2; + // Open all loaded tex + quint32 texID = 0; + for (const QString &texName : textureFiles) { + QImage tex = openTexture(texName % ".tex"); + if (!tex.isNull()) { + _loadedTex.insert(texID, tex); + } else { + qWarning() << "FieldModelFilePC::load error texture" << texName; + } + ++texID; } +} - CharArchive *charLgp = CharArchive::instance(); - if (!charLgp->isOpen()) { +quint8 FieldModelFilePC::load(CharArchive *charLgp, const QString &hrc, const QString &a, bool animate) +{ + if (hrc.isEmpty() || a.isEmpty() || !charLgp->isOpen()) { return 2; } _charLgp = charLgp; @@ -63,18 +73,8 @@ if (openMesh(rsdFiles, textureFiles)) { - if (openAnimation(aFilename % ".a", animate)) { - // Open all loaded tex - int texID = 0; - foreach(const QString &texName, textureFiles) { - QImage tex = openTexture(texName % ".tex"); - if (!tex.isNull()) { - _loadedTex.insert(texID, tex); - } else { - qWarning() << "FieldModelFilePC::load error texture" << hrcFilename << texName; - } - ++texID; - } + if (openAnimation(aFilename % ".a", animate) || _skeleton.boneCount() == 1) { + openTextures(textureFiles); return true; } else { @@ -90,6 +90,44 @@ return false; } +quint8 FieldModelFilePC::loadPart(CharArchive *charLgp, const QString &rsd) +{ + if (rsd.isEmpty() || !charLgp->isOpen()) { + return 2; + } + _charLgp = charLgp; + _skeleton.addBone(FieldModelBone(0.0, -1)); + + QStringList textureFiles; + if (openPart(rsd.toLower(), 0, textureFiles)) { + openTextures(textureFiles); + + return 0; + } + + qWarning() << "FieldModelFilePC::openMesh cannot open part" << rsd; + + return 1; +} + +quint8 FieldModelFilePC::load(const QString &hrc, const QString &a, bool animate) +{ + return load(CharArchive::instance(), hrc, a, animate); +} + +QHash FieldModelFilePC::loadedTextures() +{ + QHash ret; + QHashIterator it(_loadedTex); + + while (it.hasNext()) { + it.next(); + ret.insert((void *)it.key(), it.value()); + } + + return ret; +} + bool FieldModelFilePC::openSkeleton(const QString &hrcFileName, QMultiMap &rsdFiles) { HrcFile io(_charLgp->fileIO(hrcFileName)); @@ -115,7 +153,7 @@ itRsd.next(); int boneID = itRsd.key(); - foreach (const QString &rsd, itRsd.value()) { + for (const QString &rsd : itRsd.value()) { if (openPart(rsd.toLower() % ".rsd", boneID, textureFiles)) { onePartOpened = true; } else { @@ -153,7 +191,7 @@ return QImage(); } TexFile tex(texFile->readAll()); - if(!tex.isValid()) { + if (!tex.isValid()) { return QImage(); } return tex.image(); diff -Nru makoureactor-1.7.2/core/field/FieldModelFilePC.h makoureactor-1.8.0/core/field/FieldModelFilePC.h --- makoureactor-1.7.2/core/field/FieldModelFilePC.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldModelFilePC.h 2020-08-08 18:46:56.000000000 +0000 @@ -30,6 +30,8 @@ FieldModelFilePC(); inline bool translateAfter() const { return true; } void clear(); + quint8 load(CharArchive *charLgp, const QString &hrc, const QString &a, bool animate = true); + quint8 loadPart(CharArchive *charLgp, const QString &rsd); quint8 load(const QString &hrc, const QString &a, bool animate = true); inline int loadedTextureCount() const { return _loadedTex.size(); @@ -37,15 +39,20 @@ inline QImage loadedTexture(FieldModelGroup *group) { return _loadedTex.value(static_cast(group->textureRef())->id()); } + inline void *textureIdForGroup(FieldModelGroup *group) const { + return (void *)(ulong(static_cast(group->textureRef())->id())); + } + QHash loadedTextures(); private: Q_DISABLE_COPY(FieldModelFilePC) bool openSkeleton(const QString &hrcFileName, QMultiMap &rsdFiles); bool openAnimation(const QString &aFileName, bool animate = false); bool openMesh(QMultiMap &rsdFiles, QStringList &textureFiles); bool openPart(const QString &rsdFileName, int boneID, QStringList &textureFiles); + void openTextures(const QStringList &textureFiles); QImage openTexture(const QString &texFileName); CharArchive *_charLgp; - QHash _loadedTex; + QHash _loadedTex; }; #endif // FIELDMODELFILEPC_H diff -Nru makoureactor-1.7.2/core/field/FieldModelFilePS.cpp makoureactor-1.8.0/core/field/FieldModelFilePS.cpp --- makoureactor-1.7.2/core/field/FieldModelFilePS.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldModelFilePS.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -102,19 +102,19 @@ const QList &texturesRects = _textures.rects(); if (!texturesRects.isEmpty()) { - foreach (const FieldModelBone &bone, _skeleton.bones()) { + for (const FieldModelBone &bone : _skeleton.bones()) { - foreach (FieldModelPart *part, bone.parts()) { + for (FieldModelPart *part : bone.parts()) { QHash imgY; - foreach (FieldModelGroup *group, part->groups()) { + for (FieldModelGroup *group : part->groups()) { if (group->hasTexture()) { FieldModelTextureRefPS *textureRef = static_cast(group->textureRef()); if (textureRef->type() > 1) { QPoint newPos = textureRef->imgPos() + QPoint(0, imgY.value(textureRef->imgX())); int rectId = 0; - foreach (const QRect &rect, texturesRects) { + for (const QRect &rect : texturesRects) { if (rect.topLeft() == newPos) { break; } @@ -139,7 +139,7 @@ if (modelBcx.isValid()) { if (!skeleton().isEmpty()) { qWarning() << "FieldPS::fieldModel bsx present, but bcx skeleton not empty"; - foreach (const FieldModelBone &bone, skeleton().bones()) { + for (const FieldModelBone &bone : skeleton().bones()) { qDeleteAll(bone.parts()); } } @@ -195,9 +195,26 @@ return tex; } +QHash FieldModelFilePS::loadedTextures() +{ + QHash ret; + + for (const FieldModelBone &bone : _skeleton.bones()) { + for (FieldModelPart *part : bone.parts()) { + for (FieldModelGroup *group : part->groups()) { + if (group->hasTexture()) { + ret.insert((void *)group, loadedTexture(group)); + } + } + } + } + + return ret; +} + QImage FieldModelFilePS::vramImage() const { - foreach (const QRect &rect, _textures.rects()) { + for (const QRect &rect : _textures.rects()) { if (rect.height() == 1) { return _textures.toImage(rect.topLeft(), FieldModelTexturesPS::Bpp8); } diff -Nru makoureactor-1.7.2/core/field/FieldModelFilePS.h makoureactor-1.8.0/core/field/FieldModelFilePS.h --- makoureactor-1.7.2/core/field/FieldModelFilePS.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldModelFilePS.h 2020-08-08 18:46:56.000000000 +0000 @@ -52,6 +52,10 @@ } bool load(FieldPS *currentField, int modelID, int animationID, bool animate); QImage loadedTexture(FieldModelGroup *group); + inline void *textureIdForGroup(FieldModelGroup *group) const { + return (void *)group; + } + QHash loadedTextures(); QImage vramImage() const; private: Q_DISABLE_COPY(FieldModelFilePS) diff -Nru makoureactor-1.7.2/core/field/FieldModelLoaderPC.cpp makoureactor-1.8.0/core/field/FieldModelLoaderPC.cpp --- makoureactor-1.7.2/core/field/FieldModelLoaderPC.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldModelLoaderPC.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -37,17 +37,17 @@ void FieldModelLoaderPC::clean() { - for(int modelID=0 ; modelID animUnknown = QVector(3, 1).toList(); + model_anims_unknown.clear(); + model_anims_unknown.append(animUnknown); + model_anims_unknown.append(animUnknown); + model_anims_unknown.append(animUnknown); + + model_unknown.clear(); + model_unknown.append(0); + model_unknown.append(0); + model_unknown.append(0); + + model_typeHRC.clear(); + model_typeHRC.append(512); + model_typeHRC.append(512); + model_typeHRC.append(512); + + QList c; + c + << FieldModelColorDir(-659, 411, 4034, qRgb(128, 128, 128)) + << FieldModelColorDir(1536, -3349, -1839, qRgb(204, 204, 204)) + << FieldModelColorDir(-2920, -1474, -2484, qRgb(77, 77, 77)); + + colors.clear(); + colors.append(c); + colors.append(c); + colors.append(c); + + QRgb gc = qRgb(64, 64, 64); + + model_global_color.clear(); + model_global_color.append(gc); + model_global_color.append(gc); + model_global_color.append(gc); +} + bool FieldModelLoaderPC::open() { return open(field()->sectionData(Field::ModelLoader)); @@ -64,7 +125,7 @@ { const char *constData = data.constData(); - if((quint32)data.size() < 6) return false; + if ((quint32)data.size() < 6) return false; quint32 i, j; quint16 nb; @@ -78,15 +139,15 @@ quint16 fieldScale = field()->scriptsAndTexts()->scale(); quint32 curPos = 6; - for(i=0 ; i anims_unknown; - for(j=0 ; jmodel_nameHRC.size(); QByteArray HRCs; - for(int i=0 ; imodel_nameChar.at(i); quint16 nameSize = modelName.size(); HRCs.append((char *)&nameSize, 2); //model name size @@ -171,7 +232,7 @@ const quint16 &nbAnim = this->model_anims.at(i).size(); HRCs.append((char *)&nbAnim, 2); //Nb Anims - for(quint8 j=0 ; j<3 ; ++j) { //Colors + for (quint8 j=0; j<3; ++j) { //Colors const FieldModelColorDir &colorDir = this->colors.at(i).at(j); HRCs.append((char)qRed(colorDir.color)); HRCs.append((char)qGreen(colorDir.color)); @@ -186,7 +247,7 @@ HRCs.append((char)qGreen(globalColor)); HRCs.append((char)qBlue(globalColor)); - for(int j=0 ; jmodel_anims.at(i).at(j).size(); HRCs.append((char *)&nameSize, 2); //Animation name size HRCs.append(this->model_anims.at(i).at(j)); //Animation name @@ -209,15 +270,15 @@ bool FieldModelLoaderPC::insertModel(int modelID, const QString &hrcName) { - if(modelCount() < maxModelCount()) { + if (modelCount() < maxModelCount()) { QList color; - if(!colors.isEmpty()) { + if (!colors.isEmpty()) { color = colors.first(); } else { color = QVector(10, FieldModelColorDir()).toList(); } QRgb globalColor; - if(!model_global_color.isEmpty()) { + if (!model_global_color.isEmpty()) { globalColor = model_global_color.first(); } else { globalColor = Qt::black; @@ -241,7 +302,7 @@ void FieldModelLoaderPC::removeModel(int modelID) { - if(modelID >= 0 && modelID < modelCount()) { + if (modelID >= 0 && modelID < modelCount()) { model_unknown.removeAt(modelID); model_nameChar.removeAt(modelID); model_nameHRC.removeAt(modelID); @@ -258,7 +319,7 @@ void FieldModelLoaderPC::swapModel(int oldModelID, int newModelID) { - if(oldModelID != newModelID + if (oldModelID != newModelID && oldModelID >= 0 && oldModelID < modelCount() && newModelID >= 0 && newModelID < modelCount()) { model_unknown.swap(oldModelID, newModelID); @@ -287,7 +348,7 @@ void FieldModelLoaderPC::setHRCName(int modelID, const QString &HRCName) { - if(modelID >= 0 && modelID < model_nameHRC.size() + if (modelID >= 0 && modelID < model_nameHRC.size() && model_nameHRC.at(modelID) != HRCName) { model_nameHRC.replace(modelID, HRCName); setModified(true); @@ -306,7 +367,7 @@ void FieldModelLoaderPC::setCharName(int modelID, const QString &charName) { - if(modelID >= 0 && modelID < model_nameChar.size() + if (modelID >= 0 && modelID < model_nameChar.size() && model_nameChar.at(modelID) != charName) { model_nameChar.replace(modelID, charName); setModified(true); @@ -320,7 +381,7 @@ void FieldModelLoaderPC::setScale(int modelID, quint16 scale) { - if(modelID >= 0 && modelID < model_typeHRC.size() + if (modelID >= 0 && modelID < model_typeHRC.size() && model_typeHRC.at(modelID) != scale) { model_typeHRC.replace(modelID, scale); setModified(true); @@ -334,7 +395,7 @@ void FieldModelLoaderPC::setUnknown(int modelID, quint16 unknown) { - if(modelID >= 0 && modelID < model_unknown.size() + if (modelID >= 0 && modelID < model_unknown.size() && model_unknown.at(modelID) != unknown) { model_unknown.replace(modelID, unknown); setModified(true); @@ -349,7 +410,7 @@ void FieldModelLoaderPC::setLightColors(int modelID, const QList &lightColors) { - if(modelID >= 0 && modelID < colors.size() + if (modelID >= 0 && modelID < colors.size() && colors.at(modelID) != lightColors) { colors.replace(modelID, lightColors); setModified(true); @@ -359,7 +420,7 @@ void FieldModelLoaderPC::setLightColor(int modelID, int colorID, const FieldModelColorDir &lightColor) { - if(modelID >= 0 && modelID < colors.size() + if (modelID >= 0 && modelID < colors.size() && colorID < colors.at(modelID).size() && colors.at(modelID).at(colorID) != lightColor) { colors[modelID].replace(colorID, lightColor); @@ -374,7 +435,7 @@ void FieldModelLoaderPC::setGlobalColor(int modelID, QRgb globalColor) { - if(modelID >= 0 && modelID < model_global_color.size() + if (modelID >= 0 && modelID < model_global_color.size() && model_global_color.at(modelID) != globalColor) { model_global_color.replace(modelID, globalColor); setModified(true); @@ -383,14 +444,14 @@ int FieldModelLoaderPC::animCount(int modelID) const { - if(modelID >= 0 && modelID < model_anims.size()) + if (modelID >= 0 && modelID < model_anims.size()) return model_anims.at(modelID).size(); return 0; } bool FieldModelLoaderPC::insertAnim(int modelID, int numA, const QString &name) { - if(modelID >= 0 && modelID < modelCount() && animCount(modelID) < maxAnimCount()) { + if (modelID >= 0 && modelID < modelCount() && animCount(modelID) < maxAnimCount()) { model_anims[modelID].insert(numA, name); model_anims_unknown[modelID].insert(numA, 1); setModified(true); @@ -401,7 +462,7 @@ void FieldModelLoaderPC::removeAnim(int modelID, int numA) { - if(modelID >= 0 && modelID < modelCount() + if (modelID >= 0 && modelID < modelCount() && numA >= 0 && numA < animCount(modelID)) { model_anims[modelID].removeAt(numA); model_anims_unknown[modelID].removeAt(numA); @@ -411,7 +472,7 @@ void FieldModelLoaderPC::swapAnim(int modelID, int oldNumA, int newNumA) { - if(modelID >= 0 && modelID < modelCount() + if (modelID >= 0 && modelID < modelCount() && oldNumA != newNumA && oldNumA >= 0 && oldNumA < animCount(modelID) && newNumA >= 0 && newNumA < animCount(modelID)) { @@ -433,9 +494,9 @@ void FieldModelLoaderPC::setAName(int modelID, int numA, const QString &animName) { - if(modelID >= 0 && modelID < model_anims.size()) { + if (modelID >= 0 && modelID < model_anims.size()) { QStringList &animNames = model_anims[modelID]; - if(numA >= 0 && numA < animNames.size() + if (numA >= 0 && numA < animNames.size() && animNames.at(numA) != animName) { animNames.replace(numA, animName); setModified(true); @@ -445,7 +506,7 @@ quint16 FieldModelLoaderPC::animUnknown(int modelID, int numA) const { - if(modelID < model_anims_unknown.size()) + if (modelID < model_anims_unknown.size()) return model_anims_unknown.at(modelID).value(numA); else return 0; @@ -453,9 +514,9 @@ void FieldModelLoaderPC::setAnimUnknown(int modelID, int numA, quint16 unknown) { - if(modelID >= 0 && modelID < model_anims_unknown.size()) { + if (modelID >= 0 && modelID < model_anims_unknown.size()) { QList &animUnknown = model_anims_unknown[modelID]; - if(numA >= 0 && numA < animUnknown.size() + if (numA >= 0 && numA < animUnknown.size() && animUnknown.at(numA) != unknown) { animUnknown.replace(numA, unknown); setModified(true); diff -Nru makoureactor-1.7.2/core/field/FieldModelLoaderPC.h makoureactor-1.8.0/core/field/FieldModelLoaderPC.h --- makoureactor-1.7.2/core/field/FieldModelLoaderPC.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldModelLoaderPC.h 2020-08-08 18:46:56.000000000 +0000 @@ -38,6 +38,7 @@ explicit FieldModelLoaderPC(Field *field); void clear(); void clean(); + void initEmpty(); bool open(); bool open(const QByteArray &data); QByteArray save() const; diff -Nru makoureactor-1.7.2/core/field/FieldModelLoaderPS.cpp makoureactor-1.8.0/core/field/FieldModelLoaderPS.cpp --- makoureactor-1.7.2/core/field/FieldModelLoaderPS.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldModelLoaderPS.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -16,6 +16,7 @@ ** along with this program. If not, see . ****************************************************************************/ #include "FieldModelLoaderPS.h" +#include "AFile.h" #include "Field.h" FieldModelLoaderPS::FieldModelLoaderPS(Field *field) : @@ -37,7 +38,7 @@ { const char *constData = data.constData(); - if(data.size() < 4) { + if (data.size() < 4) { return false; } @@ -45,12 +46,12 @@ memcpy(&size, constData, 2); memcpy(&modelCount, constData + 2, 2); - if(size != data.size() || (size-4) / 8 != modelCount || (size-4) % 8 != 0) { + if (size != data.size() || (size-4) / 8 != modelCount || (size-4) % 8 != 0) { qWarning() << "invalid model loader size" << size << modelCount << data.size(); return false; } - if(sizeof(FieldModelLoaderStruct) != 8) { + if (sizeof(FieldModelLoaderStruct) != 8) { qWarning() << "invalid model loader struct size" << sizeof(FieldModelLoaderStruct); Q_ASSERT(false); } @@ -59,7 +60,7 @@ FieldModelLoaderStruct modelLoader; - for(quint32 i=0 ; i= 0 && modelID < _modelLoaders.size()) + if (modelID >= 0 && modelID < _modelLoaders.size()) return _modelLoaders.at(modelID).animationCount; return 0; } @@ -108,7 +109,7 @@ quint16 FieldModelLoaderPS::unknown(int modelID) const { // TODO: returns a quint16 word? (unknown2 is quint8) - if(modelID >= 0 && modelID < _modelLoaders.size()) + if (modelID >= 0 && modelID < _modelLoaders.size()) return _modelLoaders.at(modelID).unknown2/* | (_modelLoaders.at(modelID).unknown3 << 8)*/; return 0; } @@ -116,7 +117,7 @@ void FieldModelLoaderPS::setUnknown(int modelID, quint16 unknown) { // TODO: sets a quint16 word? - if(modelID >= 0 && modelID < _modelLoaders.size() + if (modelID >= 0 && modelID < _modelLoaders.size() && _modelLoaders.at(modelID).unknown2 != unknown) { _modelLoaders[modelID].unknown2 = unknown; setModified(true); @@ -130,9 +131,66 @@ void FieldModelLoaderPS::setModel(int modelID, const FieldModelLoaderStruct &modelLoader) { - if(modelID >= 0 && modelID < _modelLoaders.size() + if (modelID >= 0 && modelID < _modelLoaders.size() && memcmp(&modelLoader, &_modelLoaders.at(modelID), sizeof(FieldModelLoaderStruct)) != 0) { _modelLoaders.replace(modelID, modelLoader); setModified(true); } } + +FieldModelLoaderPC FieldModelLoaderPS::toPC(BsxFile *bsx, bool *ok) const +{ + FieldModelLoaderPC ret(field()); + + int i = 0; + *ok = true; + + for (const FieldModelLoaderStruct &psLoader : _modelLoaders) { + FieldModelFilePS modelFile; + + if (!bsx->seek(psLoader.modelID)) { + *ok = false; + return ret; + } + + if (!bsx->read(&modelFile)) { + *ok = false; + return ret; + } + + QString fileName; + + switch (psLoader.modelID) { + case 1: fileName = "AAAA"; break; // Cloud + case 2: fileName = "AUFF"; break; // Aerith + case 3: fileName = "ACGD"; break; // Barret + case 4: fileName = "AAGB"; break; // Tifa + case 5: fileName = "ADDA"; break; // Red XIII + case 6: fileName = "ABDA"; break; // Cid + case 7: fileName = "ABJB"; break; // Yuffie + case 8: fileName = "AEBC"; break; // Cait Sith + case 9: fileName = "AEHD"; break; // Vincent + default: + // FIXME: not the same model + fileName = "AAAA"; + break; + } + + ret.insertModel(i, fileName + ".HRC"); + + for (int j = 0; j < psLoader.animationCount; ++j) { + ret.insertAnim(i, j, "ACFE"); + ret.setAnimUnknown(i, j, 1); + } + + ret.setScale(i, modelFile.scale()); + ret.setUnknown(i, psLoader.unknown2); + ret.setGlobalColor(i, modelFile.globalColor()); + ret.setLightColors(i, modelFile.lightColors()); + + i += 1; + } + + + return ret; +} diff -Nru makoureactor-1.7.2/core/field/FieldModelLoaderPS.h makoureactor-1.8.0/core/field/FieldModelLoaderPS.h --- makoureactor-1.7.2/core/field/FieldModelLoaderPS.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldModelLoaderPS.h 2020-08-08 18:46:56.000000000 +0000 @@ -20,6 +20,8 @@ #include #include "FieldModelLoader.h" +#include "FieldModelLoaderPC.h" +#include "BsxFile.h" struct FieldModelLoaderStruct { quint8 faceID, bonesCount, partsCount, animationCount; @@ -40,6 +42,7 @@ void setUnknown(int modelID, quint16 unknown); const FieldModelLoaderStruct &model(int modelID) const; void setModel(int modelID, const FieldModelLoaderStruct &modelLoader); + FieldModelLoaderPC toPC(BsxFile *bsx, bool *ok) const; private: QList _modelLoaders; }; diff -Nru makoureactor-1.7.2/core/field/FieldModelPart.cpp makoureactor-1.8.0/core/field/FieldModelPart.cpp --- makoureactor-1.7.2/core/field/FieldModelPart.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldModelPart.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -48,7 +48,7 @@ _texCoords = texCoords; } -const PolyVertex &Poly::vertex(quint8 id) const +const PolyVertex &Poly::vertex(int id) const { return _vertices.at(id); } @@ -58,17 +58,17 @@ return _colors.first(); } -QRgb Poly::color(quint8 id) const +QRgb Poly::color(int id) const { return _colors.value(id, _colors.first()); } -const TexCoord &Poly::texCoord(quint8 id) const +const TexCoord &Poly::texCoord(int id) const { return _texCoords.at(id); } -void Poly::setTexCoord(quint8 id, const TexCoord &texCoord) +void Poly::setTexCoord(int id, const TexCoord &texCoord) { _texCoords.replace(id, texCoord); } @@ -90,11 +90,11 @@ _vertices.swap(2, 3); - if(colors.size() == 4) { + if (colors.size() == 4) { _colors.swap(2, 3); } - if(!texCoords.isEmpty()) { + if (!texCoords.isEmpty()) { _texCoords.swap(2, 3); } } @@ -106,7 +106,7 @@ _vertices.swap(2, 3); - if(!texCoords.isEmpty()) { + if (!texCoords.isEmpty()) { _texCoords.swap(2, 3); } } @@ -152,9 +152,9 @@ float minX = -1, minY = -1; - foreach (Poly *poly, polygons()) { + for (Poly *poly : polygons()) { if (poly->hasTexture() && poly->count() > 0) { - for (quint16 i = 0 ; i < (quint8)poly->count(); ++i) { + for (quint16 i = 0; i < (quint8)poly->count(); ++i) { const TexCoord &texCoord = poly->texCoord(i); if (minX < 0) { minX = texCoord.x; @@ -182,7 +182,7 @@ minY = 0; } - foreach (Poly *poly, polygons()) { + for (Poly *poly : polygons()) { if (poly->hasTexture()) { for (quint16 i = 0; i < (quint8)poly->count(); ++i) { TexCoord texCoord = poly->texCoord(i); @@ -204,7 +204,7 @@ void FieldModelGroup::setFloatCoords(float texWidth, float texHeight) const { - foreach (Poly *poly, polygons()) { + for (Poly *poly : polygons()) { if (poly->hasTexture()) { for (quint16 i = 0; i < (quint8)poly->count(); ++i) { TexCoord texCoord = poly->texCoord(i); @@ -236,16 +236,16 @@ QString ret; int groupID = 0; - foreach(FieldModelGroup *group, _groups) { + for (FieldModelGroup *group : _groups) { ret.append(QString("==== GROUP %1 ==== texNumber: %2\n") .arg(groupID) .arg(group->textureRef()->textureIdentifier())); int ID = 0; - foreach(Poly *poly, group->polygons()) { + for (Poly *poly : group->polygons()) { ret.append(QString("==== poly %1 ====\n").arg(ID)); - for(int i=0 ; icount() ; ++i) { + for (int i=0; icount(); ++i) { ret.append(QString("%1: vertex(%2, %3, %4) color(%5, %6, %7)") .arg(i) .arg(poly->vertex(i).x) @@ -254,7 +254,7 @@ .arg(qRed(poly->color(i))) .arg(qGreen(poly->color(i))) .arg(qBlue(poly->color(i)))); - if(poly->hasTexture()) { + if (poly->hasTexture()) { ret.append(QString(" texCoord(%1, %2)") .arg(poly->texCoord(i).x) .arg(poly->texCoord(i).y)); diff -Nru makoureactor-1.7.2/core/field/FieldModelPart.h makoureactor-1.8.0/core/field/FieldModelPart.h --- makoureactor-1.7.2/core/field/FieldModelPart.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldModelPart.h 2020-08-08 18:46:56.000000000 +0000 @@ -41,11 +41,11 @@ inline int count() const { return _count; } - const PolyVertex &vertex(quint8 id) const; + const PolyVertex &vertex(int id) const; const QRgb &color() const; - QRgb color(quint8 id) const; - const TexCoord &texCoord(quint8 id) const; - void setTexCoord(quint8 id, const TexCoord &texCoord); + QRgb color(int id) const; + const TexCoord &texCoord(int id) const; + void setTexCoord(int id, const TexCoord &texCoord); bool isMonochrome() const; bool hasTexture() const; protected: diff -Nru makoureactor-1.7.2/core/field/FieldModelSkeleton.cpp makoureactor-1.8.0/core/field/FieldModelSkeleton.cpp --- makoureactor-1.7.2/core/field/FieldModelSkeleton.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldModelSkeleton.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -37,7 +37,7 @@ QString ret; int boneID=0; - foreach(const FieldModelBone &bone, _bones) { + for (const FieldModelBone &bone : _bones) { ret.append(QString("Bone %1: parent= %2 size= %3\n") .arg(boneID) .arg(bone.parent()) diff -Nru makoureactor-1.7.2/core/field/FieldModelSkeleton.h makoureactor-1.8.0/core/field/FieldModelSkeleton.h --- makoureactor-1.7.2/core/field/FieldModelSkeleton.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldModelSkeleton.h 2020-08-08 18:46:56.000000000 +0000 @@ -87,10 +87,10 @@ inline bool isEmpty() const { return _bones.isEmpty(); } - inline const FieldModelBone &operator[](uint i) const { + inline const FieldModelBone &operator[](int i) const { return _bones[i]; } - inline FieldModelBone &operator[](uint i) { + inline FieldModelBone &operator[](int i) { return _bones[i]; } QString toString() const; diff -Nru makoureactor-1.7.2/core/field/FieldModelTextureRefPS.cpp makoureactor-1.8.0/core/field/FieldModelTextureRefPS.cpp --- makoureactor-1.7.2/core/field/FieldModelTextureRefPS.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldModelTextureRefPS.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -41,7 +41,7 @@ QPixmap image(720, 512); QPainter p(&image); - foreach (const QRect &rect, rects()) { + for (const QRect &rect : rects()) { if (rect.height() != 1) { p.drawImage(rect.topLeft(), toImage(rect.topLeft(), palPos, bpp)); } @@ -56,7 +56,7 @@ palId = -1, i = 0; - foreach (const QRect &rect, _rects) { + for (const QRect &rect : _rects) { if (imgId < 0 && rect.topLeft() == imgPos) { imgId = i; } else if (palId < 0 && rect.topLeft() == palPos) { diff -Nru makoureactor-1.7.2/core/field/FieldPart.h makoureactor-1.8.0/core/field/FieldPart.h --- makoureactor-1.7.2/core/field/FieldPart.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldPart.h 2020-08-08 18:46:56.000000000 +0000 @@ -28,6 +28,7 @@ explicit FieldPart(Field *field); virtual ~FieldPart(); + virtual void initEmpty() {} virtual bool open()=0; virtual bool open(const QByteArray &data)=0; virtual QByteArray save() const=0; diff -Nru makoureactor-1.7.2/core/field/FieldPC.cpp makoureactor-1.8.0/core/field/FieldPC.cpp --- makoureactor-1.7.2/core/field/FieldPC.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldPC.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -17,12 +17,20 @@ ****************************************************************************/ #include "FieldPC.h" #include "BackgroundFilePC.h" +#include "BackgroundTiles.h" +#include "FieldModelLoaderPS.h" +#include "core/LZS.h" FieldPC::FieldPC(const QString &name, FieldArchiveIO *io) : Field(name, io), _model(0) { } +FieldPC::FieldPC(const QString &name) : + Field(name, nullptr), _model(0) +{ +} + FieldPC::FieldPC(const Field &field) : Field(field), _model(0) { @@ -30,7 +38,7 @@ FieldPC::~FieldPC() { - if(_model) { + if (_model) { delete _model; } } @@ -42,14 +50,14 @@ int FieldPC::sectionId(FieldSection part) const { - switch(part) { + switch (part) { case Scripts: case Akaos: return 0; case Camera: return 1; case ModelLoader: return 2; case PalettePC: return 3; case Walkmesh: return 4; - case Unused: return 5; + case Tiles: return 5; case Encounter: return 6; case Inf: return 7; case Background: return 8; @@ -62,14 +70,9 @@ return sectionPositions[idPart] + paddingBetweenSections(); } -FieldArchiveIOPC *FieldPC::io() const -{ - return static_cast(Field::io()); -} - FieldPart *FieldPC::createPart(FieldSection part) { - switch(part) { + switch (part) { case ModelLoader: return new FieldModelLoaderPC(this); case Background: return new BackgroundFilePC(this); default: return Field::createPart(part); @@ -78,7 +81,7 @@ FieldModelLoaderPC *FieldPC::fieldModelLoader(bool open) { - //if(open && !modelLoader->isOpen()) { + //if (open && !modelLoader->isOpen()) { // Data::currentCharNames = model_nameChar; // Data::currentHrcNames = &fieldModelLoader->model_nameHRC; // Data::currentAnimNames = &fieldModelLoader->model_anims; @@ -94,13 +97,13 @@ // Optimization: Prevent the loading of the same model twice int localModelID = modelNameToId.value(hrc.toLower(), -1); - if(localModelID == -1) { + if (localModelID == -1) { localModelID = modelID; modelNameToId.insert(hrc.toLower(), localModelID); } FieldModelFilePC *fieldModel = new FieldModelFilePC(); - if(open) { + if (open) { fieldModel->load(hrc, a, animate); } return fieldModel; @@ -108,7 +111,9 @@ FieldModelFilePC *FieldPC::fieldModel(const QString &hrc, const QString &a, bool animate) { - if(!_model) _model = new FieldModelFilePC(); + if (!_model) { + _model = new FieldModelFilePC(); + } _model->load(hrc, a, animate); return _model; } @@ -128,25 +133,43 @@ QList FieldPC::orderOfSections() const { - return QList() << Scripts << Camera << ModelLoader << PalettePC << Walkmesh << Unused << Encounter << Inf << Background; + return QList() << Scripts << Camera << ModelLoader << PalettePC << Walkmesh << Tiles << Encounter << Inf << Background; } -qint8 FieldPC::importer(const QByteArray &data, bool isPSField, FieldSections part) +bool FieldPC::importModelLoader(const QByteArray §ionData, bool isPSField, QIODevice *bsxDevice) { - if(!isPSField) { - quint32 sectionPositions[9]; + FieldModelLoaderPC *modelLoader = fieldModelLoader(false); + + if (isPSField) { + FieldModelLoaderPS modelLoaderPS(this); + if (!modelLoaderPS.open(sectionData)) { + return false; + } + if (!bsxDevice->open(QIODevice::ReadOnly)) { + return false; + } - if(data.size() < 6 + 9 * 4) return 3; - memcpy(sectionPositions, data.constData() + 6, 9 * 4); // header + QByteArray decompressedBsx = LZS::decompressAllWithHeader(bsxDevice->readAll()); + QBuffer bsxDeviceDec; + bsxDeviceDec.setData(decompressedBsx); + bsxDeviceDec.open(QIODevice::ReadOnly); + + BsxFile bsx(&bsxDeviceDec); + bool ok; + *modelLoader = modelLoaderPS.toPC(&bsx, &ok); - if(part.testFlag(ModelLoader)) { - FieldModelLoaderPC *modelLoader = fieldModelLoader(false); - if(!modelLoader->open(data.mid(sectionPositions[2]+4, sectionPositions[3]-sectionPositions[2]-4))) { - return 2; - } - modelLoader->setModified(true); + if (!ok) { + return false; + } + } else { + FieldModelLoaderPC *modelLoader = fieldModelLoader(false); + if (!modelLoader->open(sectionData)) { + return false; } } - return Field::importer(data, isPSField, part); + modelLoader->setModified(true); + modelLoader->setOpen(true); + + return true; } diff -Nru makoureactor-1.7.2/core/field/FieldPC.h makoureactor-1.8.0/core/field/FieldPC.h --- makoureactor-1.7.2/core/field/FieldPC.h 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldPC.h 2020-08-08 18:46:56.000000000 +0000 @@ -28,18 +28,15 @@ { public: FieldPC(const QString &name, FieldArchiveIO *io); + FieldPC(const QString &name); explicit FieldPC(const Field &field); virtual ~FieldPC(); inline bool isPC() const { return true; } - using Field::importer; - qint8 importer(const QByteArray &data, bool isPSField, FieldSections part); - FieldModelLoaderPC *fieldModelLoader(bool open=true); FieldModelFilePC *fieldModel(int modelID, int animationID = 0, bool animate = true, bool open = true); FieldModelFilePC *fieldModel(const QString &hrc, const QString &a, bool animate = true); - FieldArchiveIOPC *io() const; protected: inline int headerSize() const { return 42; } void openHeader(const QByteArray &fileData); @@ -58,6 +55,7 @@ QList orderOfSections() const; inline quint32 diffSectionPos() const { return 0; } inline bool hasSectionHeader() const { return true; } + bool importModelLoader(const QByteArray §ionData, bool isPSField, QIODevice *bsxDevice); private: quint32 sectionPositions[9]; FieldModelFilePC *_model; diff -Nru makoureactor-1.7.2/core/field/FieldPS.cpp makoureactor-1.8.0/core/field/FieldPS.cpp --- makoureactor-1.7.2/core/field/FieldPS.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldPS.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -33,18 +33,19 @@ memcpy(sectionPositions, fileData.constData(), headerSize()); // header vramDiff = sectionPositions[0] - headerSize();// vram section1 pos - real section 1 pos - for(int i=0 ; i<7 ; ++i) { + for (int i=0; i<7; ++i) { sectionPositions[i] -= vramDiff; } } int FieldPS::sectionId(FieldSection part) const { - switch(part) { + switch (part) { case Scripts: case Akaos: return 0; case Walkmesh: return 1; - case Background: return 2; + case Background: + case Tiles: return 2; case Camera: return 3; case Inf: return 4; case Encounter: return 5; @@ -65,7 +66,7 @@ FieldPart *FieldPS::createPart(FieldSection part) { - switch(part) { + switch (part) { case ModelLoader: return new FieldModelLoaderPS(this); case Background: return new BackgroundFilePS(this); default: return Field::createPart(part); @@ -80,7 +81,7 @@ FieldModelFilePS *FieldPS::fieldModel(int modelID, int animationID, bool animate, bool open) { FieldModelFilePS *fieldModel = new FieldModelFilePS(); - if(open) { + if (open) { fieldModel->load(this, modelID, animationID, animate); } return fieldModel; diff -Nru makoureactor-1.7.2/core/field/FieldPSDemo.cpp makoureactor-1.8.0/core/field/FieldPSDemo.cpp --- makoureactor-1.7.2/core/field/FieldPSDemo.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/FieldPSDemo.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -24,7 +24,7 @@ QString FieldPSDemo::sectionFile(FieldSection part) const { - switch(part) { + switch (part) { case Scripts: return "ATE"; case Akaos: return "ATE"; case Walkmesh: return "ID"; @@ -45,7 +45,7 @@ FieldPart *FieldPSDemo::createPart(FieldSection part) { - switch(part) { + switch (part) { case ModelLoader: return new FieldModelLoaderPS(this); case Background: return new BackgroundFilePS(this); default: return Field::createPart(part); diff -Nru makoureactor-1.7.2/core/field/GrpScript.cpp makoureactor-1.8.0/core/field/GrpScript.cpp --- makoureactor-1.7.2/core/field/GrpScript.cpp 2016-11-12 20:46:36.000000000 +0000 +++ makoureactor-1.8.0/core/field/GrpScript.cpp 2020-08-08 18:46:56.000000000 +0000 @@ -17,6 +17,7 @@ ****************************************************************************/ #include "GrpScript.h" #include "../FF7Text.h" +#include "../../Data.h" ScriptsIterator::ScriptsIterator(const ScriptsIterator &other) : QListIterator