diff --git a/forms/mainwindow.ui b/forms/mainwindow.ui
index 8b4a5dd4..d63110e7 100644
--- a/forms/mainwindow.ui
+++ b/forms/mainwindow.ui
@@ -2642,6 +2642,8 @@
+
+
diff --git a/include/core/mapparser.h b/include/core/mapparser.h
new file mode 100644
index 00000000..21e3074e
--- /dev/null
+++ b/include/core/mapparser.h
@@ -0,0 +1,16 @@
+#ifndef MAPPARSER_H
+#define MAPPARSER_H
+
+#include "maplayout.h"
+#include "project.h"
+#include
+#include
+
+class MapParser
+{
+public:
+ MapParser();
+ MapLayout *parse(QString filepath, bool *error, Project *project);
+};
+
+#endif // MAPPARSER_H
diff --git a/include/mainwindow.h b/include/mainwindow.h
index 5481a3e4..a0fb8ae8 100644
--- a/include/mainwindow.h
+++ b/include/mainwindow.h
@@ -132,8 +132,10 @@ private slots:
void onTilesetsSaved(QString, QString);
void onWildMonDataChanged();
void openNewMapPopupWindow(int, QVariant);
+ void openNewMapPopupWindowImportMap(MapLayout *);
void onNewMapCreated();
void onMapCacheCleared();
+ void importMapFromAdvanceMap1_92();
void onMapRulerStatusChanged(const QString &);
void applyUserShortcuts();
@@ -193,6 +195,7 @@ private slots:
void on_action_Export_Map_Image_triggered();
void on_actionExport_Stitched_Map_Image_triggered();
void on_actionExport_Map_Timelapse_Image_triggered();
+ void on_actionImport_Map_from_Advance_Map_1_92_triggered();
void on_comboBox_ConnectionDirection_currentTextChanged(const QString &arg1);
void on_spinBox_ConnectionOffset_valueChanged(int offset);
diff --git a/include/project.h b/include/project.h
index 355ba6ba..da5ade6b 100644
--- a/include/project.h
+++ b/include/project.h
@@ -93,6 +93,7 @@ public:
Tileset* loadTileset(QString, Tileset *tileset = nullptr);
Tileset* getTileset(QString, bool forceLoad = false);
QMap tilesetLabels;
+ QList tilesetLabelsOrdered;
Blockdata readBlockdata(QString);
bool loadBlockdata(MapLayout*);
@@ -103,7 +104,7 @@ public:
void deleteFile(QString path);
bool readMapGroups();
- Map* addNewMapToGroup(QString, int, Map*, bool);
+ Map* addNewMapToGroup(QString, int, Map*, bool, bool);
QString getNewMapName();
QString getProjectTitle();
diff --git a/include/ui/newmappopup.h b/include/ui/newmappopup.h
index c77470ca..5c4f5761 100644
--- a/include/ui/newmappopup.h
+++ b/include/ui/newmappopup.h
@@ -20,8 +20,10 @@ public:
Map *map;
int group;
bool existingLayout;
+ bool importedMap;
QString layoutId;
void init(int, int, QString, QString);
+ void initImportMap(MapLayout *);
void useLayout(QString);
void connectSignals();
@@ -32,6 +34,8 @@ private:
Ui::NewMapPopup *ui;
Project *project;
void setDefaultValues(int, QString);
+ void setDefaultValuesImportMap(MapLayout *);
+ void setDefaultValuesProjectConfig(bool, MapLayout*);
bool checkNewMapDimensions();
bool checkNewMapGroup();
diff --git a/porymap.pro b/porymap.pro
index dd263db3..b6863c3c 100644
--- a/porymap.pro
+++ b/porymap.pro
@@ -22,6 +22,7 @@ SOURCES += src/core/block.cpp \
src/core/imageexport.cpp \
src/core/map.cpp \
src/core/maplayout.cpp \
+ src/core/mapparser.cpp \
src/core/metatile.cpp \
src/core/metatileparser.cpp \
src/core/paletteutil.cpp \
@@ -93,6 +94,7 @@ HEADERS += include/core/block.h \
include/core/map.h \
include/core/mapconnection.h \
include/core/maplayout.h \
+ include/core/mapparser.h \
include/core/metatile.h \
include/core/metatileparser.h \
include/core/paletteutil.h \
diff --git a/src/core/mapparser.cpp b/src/core/mapparser.cpp
new file mode 100644
index 00000000..88592ab0
--- /dev/null
+++ b/src/core/mapparser.cpp
@@ -0,0 +1,97 @@
+#include "mapparser.h"
+#include "config.h"
+#include "log.h"
+#include "project.h"
+
+MapParser::MapParser()
+{
+}
+
+MapLayout *MapParser::parse(QString filepath, bool *error, Project *project)
+{
+ QFile file(filepath);
+ if (!file.open(QIODevice::ReadOnly)) {
+ *error = true;
+ logError(QString("Could not open Advance Map 1.92 Map .map file '%1': ").arg(filepath) + file.errorString());
+ return nullptr;
+ }
+
+ QByteArray in = file.readAll();
+ file.close();
+
+ if (in.length() < 20 || in.length() % 2 != 0) {
+ *error = true;
+ logError(QString("Advance Map 1.92 Map .map file '%1' is an unexpected size.").arg(filepath));
+ return nullptr;
+ }
+
+ int borderWidth = static_cast(in.at(16)); // 0 in RSE .map files
+ int borderHeight = static_cast(in.at(17)); // 0 in RSE .map files
+ int numBorderTiles = borderWidth * borderHeight; // 0 if RSE
+
+ int mapDataOffset = 20 + (numBorderTiles * 2); // FRLG .map files store border metatile data after the header
+ int mapWidth = static_cast(in.at(0)) |
+ (static_cast(in.at(1)) << 8) |
+ (static_cast(in.at(2)) << 16) |
+ (static_cast(in.at(3)) << 24);
+ int mapHeight = static_cast(in.at(4)) |
+ (static_cast(in.at(5)) << 8) |
+ (static_cast(in.at(6)) << 16) |
+ (static_cast(in.at(7)) << 24);
+ int mapPrimaryTilesetNum = static_cast(in.at(8)) |
+ (static_cast(in.at(9)) << 8) |
+ (static_cast(in.at(10)) << 16) |
+ (static_cast(in.at(11)) << 24);
+ int mapSecondaryTilesetNum = static_cast(in.at(12)) |
+ (static_cast(in.at(13)) << 8) |
+ (static_cast(in.at(14)) << 16) |
+ (static_cast(in.at(15)) << 24);
+
+ int numMetatiles = mapWidth * mapHeight;
+ int expectedFileSize = 20 + (numBorderTiles * 2) + (numMetatiles * 2);
+ if (in.length() != expectedFileSize) {
+ *error = true;
+ logError(QString(".map file is an unexpected size. Expected %1 bytes, but it has %2 bytes.").arg(expectedFileSize).arg(in.length()));
+ return nullptr;
+ }
+
+ Blockdata blockdata;
+ for (int i = mapDataOffset; (i + 1) < in.length(); i += 2) {
+ uint16_t word = static_cast((in[i] & 0xff) + ((in[i + 1] & 0xff) << 8));
+ blockdata.append(word);
+ }
+
+ Blockdata border;
+ if (numBorderTiles != 0) {
+ for (int i = 20; (i + 1) < mapDataOffset; i += 2) {
+ uint16_t word = static_cast((in[i] & 0xff) + ((in[i + 1] & 0xff) << 8));
+ border.append(word);
+ }
+ }
+
+ MapLayout *mapLayout = new MapLayout();
+ mapLayout->width = QString::number(mapWidth);
+ mapLayout->height = QString::number(mapHeight);
+ mapLayout->border_width = (borderWidth == 0) ? QString::number(2) : QString::number(borderWidth);
+ mapLayout->border_height = (borderHeight == 0) ? QString::number(2) : QString::number(borderHeight);
+
+ QList tilesets = project->tilesetLabelsOrdered;
+
+ if (mapPrimaryTilesetNum > tilesets.size())
+ mapLayout->tileset_primary_label = tilesets.at(0);
+ else
+ mapLayout->tileset_primary_label = tilesets.at(mapPrimaryTilesetNum);
+
+ if (mapSecondaryTilesetNum > tilesets.size())
+ mapLayout->tileset_secondary_label = tilesets.at(1);
+ else
+ mapLayout->tileset_secondary_label = tilesets.at(mapSecondaryTilesetNum);
+
+ mapLayout->blockdata = blockdata;
+
+ if (!border.isEmpty()) {
+ mapLayout->border = border;
+ }
+
+ return mapLayout;
+}
diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp
index 69e1ba1a..7a1bc40f 100644
--- a/src/mainwindow.cpp
+++ b/src/mainwindow.cpp
@@ -15,6 +15,7 @@
#include "editcommands.h"
#include "flowlayout.h"
#include "shortcut.h"
+#include "mapparser.h"
#include
#include
@@ -1161,8 +1162,9 @@ void MainWindow::onNewMapCreated() {
int newMapGroup = this->newmapprompt->group;
Map *newMap = this->newmapprompt->map;
bool existingLayout = this->newmapprompt->existingLayout;
+ bool importedMap = this->newmapprompt->importedMap;
- newMap = editor->project->addNewMapToGroup(newMapName, newMapGroup, newMap, existingLayout);
+ newMap = editor->project->addNewMapToGroup(newMapName, newMapGroup, newMap, existingLayout, importedMap);
logInfo(QString("Created a new map named %1.").arg(newMapName));
@@ -1215,6 +1217,24 @@ void MainWindow::openNewMapPopupWindow(int type, QVariant data) {
this->newmapprompt->setAttribute(Qt::WA_DeleteOnClose);
}
+void MainWindow::openNewMapPopupWindowImportMap(MapLayout *mapLayout) {
+ if (!this->newmapprompt) {
+ this->newmapprompt = new NewMapPopup(this, this->editor->project);
+ }
+ if (!this->newmapprompt->isVisible()) {
+ this->newmapprompt->show();
+ } else {
+ this->newmapprompt->raise();
+ this->newmapprompt->activateWindow();
+ }
+
+ this->newmapprompt->initImportMap(mapLayout);
+
+ connect(this->newmapprompt, SIGNAL(applied()), this, SLOT(onNewMapCreated()));
+ connect(this->newmapprompt, &QObject::destroyed, [=](QObject *) { this->newmapprompt = nullptr; });
+ this->newmapprompt->setAttribute(Qt::WA_DeleteOnClose);
+}
+
void MainWindow::on_action_NewMap_triggered() {
openNewMapPopupWindow(MapSortOrder::Group, 0);
}
@@ -2726,6 +2746,38 @@ void MainWindow::on_actionExport_Map_Timelapse_Image_triggered() {
showExportMapImageWindow(ImageExporterMode::Timelapse);
}
+void MainWindow::on_actionImport_Map_from_Advance_Map_1_92_triggered(){
+ importMapFromAdvanceMap1_92();
+}
+
+void MainWindow::importMapFromAdvanceMap1_92()
+{
+ QString filepath = QFileDialog::getOpenFileName(
+ this,
+ QString("Import Map from Advance Map 1.92"),
+ this->editor->project->root,
+ "Advance Map 1.92 Map Files (*.map)");
+ if (filepath.isEmpty()) {
+ return;
+ }
+
+ MapParser parser;
+ bool error = false;
+ MapLayout *mapLayout = parser.parse(filepath, &error, editor->project);
+ if (error) {
+ QMessageBox msgBox(this);
+ msgBox.setText("Failed to import map from Advance Map 1.92 .map file.");
+ QString message = QString("The .map file could not be processed. View porymap.log for specific errors.");
+ msgBox.setInformativeText(message);
+ msgBox.setDefaultButton(QMessageBox::Ok);
+ msgBox.setIcon(QMessageBox::Icon::Critical);
+ msgBox.exec();
+ return;
+ }
+
+ openNewMapPopupWindowImportMap(mapLayout);
+}
+
void MainWindow::showExportMapImageWindow(ImageExporterMode mode) {
if (!editor->project) return;
diff --git a/src/project.cpp b/src/project.cpp
index 074eef4c..2bf35b8e 100644
--- a/src/project.cpp
+++ b/src/project.cpp
@@ -1848,7 +1848,7 @@ bool Project::readMapGroups() {
return true;
}
-Map* Project::addNewMapToGroup(QString mapName, int groupNum, Map *newMap, bool existingLayout) {
+Map* Project::addNewMapToGroup(QString mapName, int groupNum, Map *newMap, bool existingLayout, bool importedMap) {
mapNames.append(mapName);
mapGroups.insert(mapName, groupNum);
groupedMapNames[groupNum].append(mapName);
@@ -1861,8 +1861,12 @@ Map* Project::addNewMapToGroup(QString mapName, int groupNum, Map *newMap, bool
if (!existingLayout) {
mapLayouts.insert(newMap->layoutId, newMap->layout);
mapLayoutsTable.append(newMap->layoutId);
- setNewMapBlockdata(newMap);
- setNewMapBorder(newMap);
+ if (!importedMap) {
+ setNewMapBlockdata(newMap);
+ }
+ if (newMap->layout->border.isEmpty()) {
+ setNewMapBorder(newMap);
+ }
}
loadLayoutTilesets(newMap->layout);
@@ -1910,6 +1914,7 @@ QMap Project::getTilesetLabels() {
QStringList secondaryTilesets;
allTilesets.insert("primary", primaryTilesets);
allTilesets.insert("secondary", secondaryTilesets);
+ QList tilesetLabelsOrdered;
QString filename = "data/tilesets/headers.inc";
QString headers_text = parser.readTextFile(root + "/" + filename);
@@ -1938,8 +1943,10 @@ QMap Project::getTilesetLabels() {
allTilesets["secondary"].append(tilesetLabel);
else
allTilesets["primary"].append(tilesetLabel);
+ tilesetLabelsOrdered.append(tilesetLabel);
}
this->tilesetLabels = allTilesets;
+ this->tilesetLabelsOrdered = tilesetLabelsOrdered;
return allTilesets;
}
diff --git a/src/ui/newmappopup.cpp b/src/ui/newmappopup.cpp
index c53c6416..0d96f42b 100644
--- a/src/ui/newmappopup.cpp
+++ b/src/ui/newmappopup.cpp
@@ -17,6 +17,7 @@ NewMapPopup::NewMapPopup(QWidget *parent, Project *project) :
ui->setupUi(this);
this->project = project;
this->existingLayout = false;
+ this->importedMap = false;
}
NewMapPopup::~NewMapPopup()
@@ -41,6 +42,12 @@ void NewMapPopup::init(int type, int group, QString sec, QString layoutId) {
connectSignals();
}
+void NewMapPopup::initImportMap(MapLayout *mapLayout) {
+ this->importedMap = true;
+ setDefaultValuesImportMap(mapLayout);
+ connectSignals();
+}
+
bool NewMapPopup::checkNewMapDimensions() {
int numMetatiles = project->getMapDataSize(ui->spinBox_NewMap_Width->value(), ui->spinBox_NewMap_Height->value());
int maxMetatiles = project->getMaxMapDataSize();
@@ -136,6 +143,42 @@ void NewMapPopup::setDefaultValues(int groupNum, QString mapSec) {
ui->frame_NewMap_Options->setEnabled(true);
+ setDefaultValuesProjectConfig(false, NULL);
+}
+
+void NewMapPopup::setDefaultValuesImportMap(MapLayout *mapLayout) {
+ ui->lineEdit_NewMap_Name->setText(project->getNewMapName());
+
+ QMap tilesets = project->getTilesetLabels();
+ ui->comboBox_NewMap_Primary_Tileset->addItems(tilesets.value("primary"));
+ ui->comboBox_NewMap_Secondary_Tileset->addItems(tilesets.value("secondary"));
+
+ ui->comboBox_NewMap_Group->addItems(project->groupNames);
+ ui->comboBox_NewMap_Group->setCurrentText(project->groupNames.at(0));
+
+ ui->spinBox_NewMap_Width->setValue(mapLayout->width.toInt(nullptr, 0));
+ ui->spinBox_NewMap_Height->setValue(mapLayout->height.toInt(nullptr, 0));
+ ui->comboBox_NewMap_Primary_Tileset->setCurrentText(mapLayout->tileset_primary_label);
+ ui->comboBox_NewMap_Secondary_Tileset->setCurrentText(mapLayout->tileset_secondary_label);
+
+ ui->comboBox_NewMap_Type->addItems(project->mapTypes);
+ ui->comboBox_NewMap_Location->addItems(project->mapSectionValueToName.values());
+ ui->checkBox_NewMap_Show_Location->setChecked(true);
+
+ ui->frame_NewMap_Options->setEnabled(true);
+
+ setDefaultValuesProjectConfig(true, mapLayout);
+
+ map = new Map();
+ map->layout = new MapLayout();
+ map->layout->blockdata = mapLayout->blockdata;
+
+ if (!mapLayout->border.isEmpty()) {
+ map->layout->border = mapLayout->border;
+ }
+}
+
+void NewMapPopup::setDefaultValuesProjectConfig(bool importedMap, MapLayout *mapLayout) {
switch (projectConfig.getBaseGameVersion())
{
case BaseGameVersion::pokeruby:
@@ -164,11 +207,19 @@ void NewMapPopup::setDefaultValues(int groupNum, QString mapSec) {
break;
}
if (projectConfig.getUseCustomBorderSize()) {
+ if (importedMap) {
+ ui->spinBox_NewMap_BorderWidth->setValue(mapLayout->border_width.toInt(nullptr, 0));
+ ui->spinBox_NewMap_BorderHeight->setValue(mapLayout->border_height.toInt(nullptr, 0));
+ }
ui->spinBox_NewMap_BorderWidth->setVisible(true);
ui->spinBox_NewMap_BorderHeight->setVisible(true);
ui->label_NewMap_BorderWidth->setVisible(true);
ui->label_NewMap_BorderHeight->setVisible(true);
} else {
+ if (importedMap) {
+ ui->spinBox_NewMap_BorderWidth->setValue(DEFAULT_BORDER_WIDTH);
+ ui->spinBox_NewMap_BorderHeight->setValue(DEFAULT_BORDER_HEIGHT);
+ }
ui->spinBox_NewMap_BorderWidth->setVisible(false);
ui->spinBox_NewMap_BorderHeight->setVisible(false);
ui->label_NewMap_BorderWidth->setVisible(false);
@@ -242,6 +293,12 @@ void NewMapPopup::on_pushButton_NewMap_Accept_clicked() {
layout->blockdata_path = QString("data/layouts/%1/map.bin").arg(newMapName);
}
+ if (this->importedMap) {
+ layout->blockdata = map->layout->blockdata;
+ if (!map->layout->border.isEmpty())
+ layout->border = map->layout->border;
+ }
+
if (this->ui->checkBox_NewMap_Flyable->isChecked()) {
newMap->isFlyable = "TRUE";
}