From 731fbce6af62e9c366d4405f707a75c71bbb5277 Mon Sep 17 00:00:00 2001 From: GriffinR Date: Sat, 16 May 2020 16:57:03 -0400 Subject: [PATCH] Read MAX_MAP_DATA_SIZE --- include/mainwindow.h | 2 +- include/project.h | 9 ++++++ src/mainwindow.cpp | 30 +++++++----------- src/project.cpp | 71 ++++++++++++++++++++++++++++++++++++++++-- src/ui/newmappopup.cpp | 4 +-- 5 files changed, 91 insertions(+), 25 deletions(-) diff --git a/include/mainwindow.h b/include/mainwindow.h index 29ae028b..1bf1c54c 100644 --- a/include/mainwindow.h +++ b/include/mainwindow.h @@ -277,7 +277,7 @@ private: QString getDefaultMap(); void setRecentMap(QString map_name); QStandardItem* createMapItem(QString mapName, int groupNum, int inGroupNum); - static bool mapDimensionsValid(int width, int height); + bool mapDimensionsValid(int width, int height); void drawMapListIcons(QAbstractItemModel *model); void updateMapList(); diff --git a/include/project.h b/include/project.h index 45b73c4e..298e1351 100644 --- a/include/project.h +++ b/include/project.h @@ -184,6 +184,13 @@ public: static int getNumMetatilesTotal(); static int getNumPalettesPrimary(); static int getNumPalettesTotal(); + static int getMaxMapDataSize(); + static int getDefaultMapSize(); + static int getMaxMapWidth(); + static int getMaxMapHeight(); + + int getMapDataSize(int width, int height); + bool calculateDefaultMapSize(); private: void updateMapLayout(Map*); @@ -203,6 +210,8 @@ private: static int num_metatiles_total; static int num_pals_primary; static int num_pals_total; + static int max_map_data_size; + static int default_map_size; QWidget *parent; diff --git a/src/mainwindow.cpp b/src/mainwindow.cpp index 7afdc8a1..d33b8309 100644 --- a/src/mainwindow.cpp +++ b/src/mainwindow.cpp @@ -2291,9 +2291,8 @@ void MainWindow::on_pushButton_ChangeDimensions_clicked() heightSpinBox->setMinimum(1); bwidthSpinBox->setMinimum(1); bheightSpinBox->setMinimum(1); - // See below for explanation of maximum map dimensions - widthSpinBox->setMaximum(0x1E7); - heightSpinBox->setMaximum(0x1D1); + widthSpinBox->setMaximum(editor->project->getMaxMapWidth()); + heightSpinBox->setMaximum(editor->project->getMaxMapHeight()); // Maximum based only on data type (u8) of map border width/height bwidthSpinBox->setMaximum(255); bheightSpinBox->setMaximum(255); @@ -2319,20 +2318,20 @@ void MainWindow::on_pushButton_ChangeDimensions_clicked() QDialogButtonBox buttonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, Qt::Horizontal, &dialog); form.addRow(&buttonBox); - connect(&buttonBox, &QDialogButtonBox::accepted, [&dialog, &widthSpinBox, &heightSpinBox, &errorLabel](){ + connect(&buttonBox, &QDialogButtonBox::accepted, [&dialog, &widthSpinBox, &heightSpinBox, &errorLabel, this](){ // Ensure width and height are an acceptable size. // The maximum number of metatiles in a map is the following: // max = (width + 15) * (height + 14) - // This limit can be found in fieldmap.c in pokeruby/pokeemerald. - int realWidth = widthSpinBox->value() + 15; - int realHeight = heightSpinBox->value() + 14; - int numMetatiles = realWidth * realHeight; - if (MainWindow::mapDimensionsValid(widthSpinBox->value(), heightSpinBox->value())) { + // This limit can be found in fieldmap.c in pokeruby/pokeemerald/pokefirered. + int numMetatiles = editor->project->getMapDataSize(widthSpinBox->value(), heightSpinBox->value()); + int maxMetatiles = editor->project->getMaxMapDataSize(); + if (numMetatiles <= maxMetatiles) { dialog.accept(); } else { QString errorText = QString("Error: The specified width and height are too large.\n" - "The maximum map width and height is the following: (width + 15) * (height + 14) <= 10240\n" - "The specified map width and height was: (%1 + 15) * (%2 + 14) = %3") + "The maximum map width and height is the following: (width + 15) * (height + 14) <= %1\n" + "The specified map width and height was: (%2 + 15) * (%3 + 14) = %4") + .arg(maxMetatiles) .arg(widthSpinBox->value()) .arg(heightSpinBox->value()) .arg(numMetatiles); @@ -2353,14 +2352,7 @@ void MainWindow::on_pushButton_ChangeDimensions_clicked() } bool MainWindow::mapDimensionsValid(int width, int height) { - // Ensure width and height are an acceptable size. - // The maximum number of metatiles in a map is the following: - // max = (width + 15) * (height + 14) - // This limit can be found in fieldmap.c in pokeruby/pokeemerald. - int realWidth = width + 15; - int realHeight = height + 14; - int numMetatiles = realWidth * realHeight; - return numMetatiles <= 0x2800; + return editor->project->getMapDataSize(width, height) <= editor->project->getMaxMapDataSize(); } void MainWindow::on_checkBox_smartPaths_stateChanged(int selected) diff --git a/src/project.cpp b/src/project.cpp index 8f229863..fecc2a05 100644 --- a/src/project.cpp +++ b/src/project.cpp @@ -33,6 +33,8 @@ int Project::num_metatiles_primary = 512; int Project::num_metatiles_total = 1024; int Project::num_pals_primary = 6; int Project::num_pals_total = 13; +int Project::max_map_data_size = 10240; // 0x2800 +int Project::default_map_size = 20; Project::Project(QWidget *parent) : parent(parent) { @@ -720,8 +722,8 @@ void Project::setNewMapLayout(Map* map) { MapLayout *layout = new MapLayout(); layout->id = MapLayout::layoutConstantFromName(map->name); layout->name = QString("%1_Layout").arg(map->name); - layout->width = "20"; - layout->height = "20"; + layout->width = QString::number(getDefaultMapSize()); + layout->height = QString::number(getDefaultMapSize()); layout->border_width = DEFAULT_BORDER_WIDTH; layout->border_height = DEFAULT_BORDER_HEIGHT; layout->border_path = QString("data/layouts/%1/border.bin").arg(map->name); @@ -2044,7 +2046,7 @@ QMap Project::getTilesetLabels() { bool Project::readTilesetProperties() { QStringList definePrefixes; - definePrefixes << "NUM_"; + definePrefixes << "NUM_" << "MAX_"; QString filename = "include/fieldmap.h"; fileWatcher.addPath(root + "/" + filename); QMap defines = parser.readCDefines(filename, definePrefixes); @@ -2097,6 +2099,24 @@ bool Project::readTilesetProperties() { logWarn(QString("Value for tileset property 'NUM_PALS_TOTAL' not found. Using default (%1) instead.") .arg(Project::num_pals_total)); } + it = defines.find("MAX_MAP_DATA_SIZE"); + if (it != defines.end()) { + int min = getMapDataSize(1, 1); + if (it.value() >= min) { + Project::max_map_data_size = it.value(); + calculateDefaultMapSize(); + } else { + // must be large enough to support a 1x1 map + logWarn(QString("Value for map property 'MAX_MAP_DATA_SIZE' is %1, must be at least %2. Using default (%3) instead.") + .arg(it.value()) + .arg(min) + .arg(Project::max_map_data_size)); + } + } + else { + logWarn(QString("Value for map property 'MAX_MAP_DATA_SIZE' not found. Using default (%1) instead.") + .arg(Project::max_map_data_size)); + } return true; } @@ -2541,3 +2561,48 @@ int Project::getNumPalettesTotal() { return Project::num_pals_total; } + +int Project::getMaxMapDataSize() +{ + return Project::max_map_data_size; +} + +int Project::getMapDataSize(int width, int height) +{ + // + 15 and + 14 come from fieldmap.c in pokeruby/pokeemerald/pokefirered. + return (width + 15) * (height + 14); +} + +int Project::getDefaultMapSize() +{ + return Project::default_map_size; +} + +int Project::getMaxMapWidth() +{ + return (getMaxMapDataSize() / (1 + 14)) - 15; +} + +int Project::getMaxMapHeight() +{ + return (getMaxMapDataSize() / (1 + 15)) - 14; +} + +// Get largest possible square dimensions for a map up to maximum of 20x20 (arbitrary) +bool Project::calculateDefaultMapSize(){ + int max = getMaxMapDataSize(); + + if (max >= getMapDataSize(20, 20)) { + default_map_size = 20; + } else if (max >= getMapDataSize(1, 1)) { + // Below equation derived from max >= (x + 15) * (x + 14) + // x^2 + 29x + (10 - max), then complete the square and simplify + default_map_size = qFloor((qSqrt(4 * getMaxMapDataSize() + 1) - 29) / 2); + } else { + logError(QString("'MAX_MAP_DATA_SIZE' of %1 is too small to support a 1x1 map. Must be at least %2.") + .arg(max) + .arg(getMapDataSize(1, 1))); + return false; + } + return true; +} diff --git a/src/ui/newmappopup.cpp b/src/ui/newmappopup.cpp index f35af69e..b877eac9 100644 --- a/src/ui/newmappopup.cpp +++ b/src/ui/newmappopup.cpp @@ -67,8 +67,8 @@ void NewMapPopup::setDefaultValues(int groupNum, QString mapSec) { ui->comboBox_NewMap_Primary_Tileset->setDisabled(true); ui->comboBox_NewMap_Secondary_Tileset->setDisabled(true); } else { - ui->spinBox_NewMap_Width->setValue(20); - ui->spinBox_NewMap_Height->setValue(20); + ui->spinBox_NewMap_Width->setValue(project->getDefaultMapSize()); + ui->spinBox_NewMap_Height->setValue(project->getDefaultMapSize()); ui->spinBox_NewMap_BorderWidth->setValue(DEFAULT_BORDER_WIDTH); ui->spinBox_NewMap_BorderHeight->setValue(DEFAULT_BORDER_HEIGHT); }