Преглед на файлове

Merge pull request #23 from huderlem/items

Populate items, flags, and vars in dropdown menus
yenatch преди 6 години
родител
ревизия
470fc92fba
No account linked to committer's email address
променени са 8 файла, в които са добавени 356 реда и са изтрити 156 реда
  1. 0
    59
      asm.cpp
  2. 0
    15
      asm.h
  3. 23
    9
      mainwindow.cpp
  4. 199
    0
      parseutil.cpp
  5. 43
    0
      parseutil.h
  6. 4
    4
      pretmap.pro
  7. 78
    66
      project.cpp
  8. 9
    3
      project.h

+ 0
- 59
asm.cpp Целия файл

@@ -1,59 +0,0 @@
1
-#include "asm.h"
2
-
3
-Asm::Asm()
4
-{
5
-}
6
-
7
-void Asm::strip_comment(QString *line) {
8
-    bool in_string = false;
9
-    for (int i = 0; i < line->length(); i++) {
10
-        if (line->at(i) == '"') {
11
-            in_string = !in_string;
12
-        } else if (line->at(i) == '@') {
13
-            if (!in_string) {
14
-                line->truncate(i);
15
-                break;
16
-            }
17
-        }
18
-    }
19
-}
20
-
21
-QList<QStringList>* Asm::parse(QString text) {
22
-    QList<QStringList> *parsed = new QList<QStringList>;
23
-    QStringList lines = text.split('\n');
24
-    for (QString line : lines) {
25
-        QString label;
26
-        //QString macro;
27
-        //QStringList *params;
28
-        strip_comment(&line);
29
-        if (line.trimmed().isEmpty()) {
30
-        } else if (line.contains(':')) {
31
-            label = line.left(line.indexOf(':'));
32
-            QStringList *list = new QStringList;
33
-            list->append(".label"); // This is not a real keyword. It's used only to make the output more regular.
34
-            list->append(label);
35
-            parsed->append(*list);
36
-            // There should not be anything else on the line.
37
-            // gas will raise a syntax error if there is.
38
-        } else {
39
-            line = line.trimmed();
40
-            //parsed->append(line.split(QRegExp("\\s*,\\s*")));
41
-            QString macro;
42
-            QStringList params;
43
-            int index = line.indexOf(QRegExp("\\s+"));
44
-            macro = line.left(index);
45
-            params = line.right(line.length() - index).trimmed().split(QRegExp("\\s*,\\s*"));
46
-            params.prepend(macro);
47
-            parsed->append(params);
48
-        }
49
-        //if (macro != NULL) {
50
-        //    if (macros->contains(macro)) {
51
-        //        void* function = macros->value(macro);
52
-        //        if (function != NULL) {
53
-        //            std::function function(params);
54
-        //        }
55
-        //    }
56
-        //}
57
-    }
58
-    return parsed;
59
-}

+ 0
- 15
asm.h Целия файл

@@ -1,15 +0,0 @@
1
-#ifndef ASM_H
2
-#define ASM_H
3
-
4
-#include <QString>
5
-#include <QList>
6
-
7
-class Asm
8
-{
9
-public:
10
-    Asm();
11
-    void strip_comment(QString*);
12
-    QList<QStringList>* parse(QString);
13
-};
14
-
15
-#endif // ASM_H

+ 23
- 9
mainwindow.cpp Целия файл

@@ -203,11 +203,7 @@ void MainWindow::displayMapProperties() {
203 203
 
204 204
     QStringList songs = project->getSongNames();
205 205
     ui->comboBox_Song->addItems(songs);
206
-    QString song = map->song;
207
-    if (!songs.contains(song)) {
208
-        song = project->getSongName(song.toInt());
209
-    }
210
-    ui->comboBox_Song->setCurrentText(song);
206
+    ui->comboBox_Song->setCurrentText(map->song);
211 207
 
212 208
     ui->comboBox_Location->addItems(project->getLocations());
213 209
     ui->comboBox_Location->setCurrentText(map->location);
@@ -284,6 +280,9 @@ void MainWindow::loadDataStructures() {
284 280
     Project *project = editor->project;
285 281
     project->readMapAttributesTable();
286 282
     project->readAllMapAttributes();
283
+    project->readItemNames();
284
+    project->readFlagNames();
285
+    project->readVarNames();
287 286
 }
288 287
 
289 288
 void MainWindow::populateMapList() {
@@ -569,8 +568,8 @@ void MainWindow::updateSelectedObjects() {
569 568
         field_labels["sight_radius"] = "Sight Radius";
570 569
         field_labels["destination_warp"] = "Destination Warp";
571 570
         field_labels["destination_map_name"] = "Destination Map";
572
-        field_labels["coord_unknown1"] = "Unknown 1";
573
-        field_labels["coord_unknown2"] = "Unknown 2";
571
+        field_labels["script_var"] = "Var";
572
+        field_labels["script_var_value"] = "Var Value";
574 573
         field_labels["type"] = "Type";
575 574
         field_labels["item"] = "Item";
576 575
         field_labels["item_unknown5"] = "Unknown 5";
@@ -613,8 +612,8 @@ void MainWindow::updateSelectedObjects() {
613 612
         }
614 613
         else if (event_type == "trap") {
615 614
             fields << "script_label";
616
-            fields << "coord_unknown1";
617
-            fields << "coord_unknown2";
615
+            fields << "script_var";
616
+            fields << "script_var_value";
618 617
         }
619 618
         else if (event_type == "trap_weather") {
620 619
             fields << "weather";
@@ -644,6 +643,21 @@ void MainWindow::updateSelectedObjects() {
644 643
                     combo->addItem(value);
645 644
                 }
646 645
                 combo->addItems(*editor->project->mapNames);
646
+            } else if (key == "item") {
647
+                if (!editor->project->itemNames->contains(value)) {
648
+                    combo->addItem(value);
649
+                }
650
+                combo->addItems(*editor->project->itemNames);
651
+            } else if (key == "flag") {
652
+                if (!editor->project->flagNames->contains(value)) {
653
+                    combo->addItem(value);
654
+                }
655
+                combo->addItems(*editor->project->flagNames);
656
+            } else if (key == "script_var") {
657
+                if (!editor->project->varNames->contains(value)) {
658
+                    combo->addItem(value);
659
+                }
660
+                combo->addItems(*editor->project->varNames);
647 661
             } else {
648 662
                 combo->addItem(value);
649 663
             }

+ 199
- 0
parseutil.cpp Целия файл

@@ -0,0 +1,199 @@
1
+#include "parseutil.h"
2
+
3
+#include <QDebug>
4
+#include <QRegularExpression>
5
+#include <QStack>
6
+
7
+ParseUtil::ParseUtil()
8
+{
9
+}
10
+
11
+void ParseUtil::strip_comment(QString *line) {
12
+    bool in_string = false;
13
+    for (int i = 0; i < line->length(); i++) {
14
+        if (line->at(i) == '"') {
15
+            in_string = !in_string;
16
+        } else if (line->at(i) == '@') {
17
+            if (!in_string) {
18
+                line->truncate(i);
19
+                break;
20
+            }
21
+        }
22
+    }
23
+}
24
+
25
+QList<QStringList>* ParseUtil::parseAsm(QString text) {
26
+    QList<QStringList> *parsed = new QList<QStringList>;
27
+    QStringList lines = text.split('\n');
28
+    for (QString line : lines) {
29
+        QString label;
30
+        //QString macro;
31
+        //QStringList *params;
32
+        strip_comment(&line);
33
+        if (line.trimmed().isEmpty()) {
34
+        } else if (line.contains(':')) {
35
+            label = line.left(line.indexOf(':'));
36
+            QStringList *list = new QStringList;
37
+            list->append(".label"); // This is not a real keyword. It's used only to make the output more regular.
38
+            list->append(label);
39
+            parsed->append(*list);
40
+            // There should not be anything else on the line.
41
+            // gas will raise a syntax error if there is.
42
+        } else {
43
+            line = line.trimmed();
44
+            //parsed->append(line.split(QRegExp("\\s*,\\s*")));
45
+            QString macro;
46
+            QStringList params;
47
+            int index = line.indexOf(QRegExp("\\s+"));
48
+            macro = line.left(index);
49
+            params = line.right(line.length() - index).trimmed().split(QRegExp("\\s*,\\s*"));
50
+            params.prepend(macro);
51
+            parsed->append(params);
52
+        }
53
+        //if (macro != NULL) {
54
+        //    if (macros->contains(macro)) {
55
+        //        void* function = macros->value(macro);
56
+        //        if (function != NULL) {
57
+        //            std::function function(params);
58
+        //        }
59
+        //    }
60
+        //}
61
+    }
62
+    return parsed;
63
+}
64
+
65
+int ParseUtil::evaluateDefine(QString define, QMap<QString, int>* knownDefines) {
66
+    QList<Token> tokens = tokenizeExpression(define, knownDefines);
67
+    QList<Token> postfixExpression = generatePostfix(tokens);
68
+    return evaluatePostfix(postfixExpression);
69
+}
70
+
71
+QList<Token> ParseUtil::tokenizeExpression(QString expression, QMap<QString, int>* knownIdentifiers) {
72
+    QList<Token> tokens;
73
+
74
+    QStringList tokenTypes = (QStringList() << "hex" << "decimal" << "identifier" << "operator" << "leftparen" << "rightparen");
75
+    QRegularExpression re("^(?<hex>0x[0-9a-fA-F]+)|(?<decimal>[0-9]+)|(?<identifier>[a-zA-Z_0-9]+)|(?<operator>[+\\-*\\/<>|^%]+)|(?<leftparen>\\()|(?<rightparen>\\))");
76
+
77
+    expression = expression.trimmed();
78
+    while (!expression.isEmpty()) {
79
+        QRegularExpressionMatch match = re.match(expression);
80
+        if (!match.hasMatch()) {
81
+            qDebug() << "Failed to tokenize expression: " << expression;
82
+            break;
83
+        }
84
+        for (QString tokenType : tokenTypes) {
85
+            QString token = match.captured(tokenType);
86
+            if (!token.isEmpty()) {
87
+                if (tokenType == "identifier") {
88
+                    if (knownIdentifiers->contains(token)) {
89
+                        QString actualToken = QString("%1").arg(knownIdentifiers->value(token));
90
+                        expression = expression.replace(0, token.length(), actualToken);
91
+                        token = actualToken;
92
+                        tokenType = "decimal";
93
+                    } else {
94
+                        qDebug() << "Unknown identifier found in expression: " << token;
95
+                    }
96
+                }
97
+
98
+                tokens.append(Token(token, tokenType));
99
+                expression = expression.remove(0, token.length()).trimmed();
100
+                break;
101
+            }
102
+        }
103
+    }
104
+    return tokens;
105
+}
106
+
107
+QMap<QString, int> Token::precedenceMap = QMap<QString, int>(
108
+{
109
+    {"*", 3},
110
+    {"/", 3},
111
+    {"+", 4},
112
+    {"-", 4},
113
+    {"<<", 5},
114
+    {">>", 5},
115
+    {"&", 8},
116
+    {"^", 9},
117
+    {"|", 10}
118
+});
119
+
120
+// Shunting-yard algorithm for generating postfix notation.
121
+// https://en.wikipedia.org/wiki/Shunting-yard_algorithm
122
+QList<Token> ParseUtil::generatePostfix(QList<Token> tokens) {
123
+    QList<Token> output;
124
+    QStack<Token> operatorStack;
125
+    for (Token token : tokens) {
126
+        if (token.type == TokenType::Number) {
127
+            output.append(token);
128
+        } else if (token.value == "(") {
129
+            operatorStack.push(token);
130
+        } else if (token.value == ")") {
131
+            while (!operatorStack.empty() && operatorStack.top().value != "(") {
132
+                output.append(operatorStack.pop());
133
+            }
134
+            if (!operatorStack.empty()) {
135
+                // pop the left parenthesis token
136
+                operatorStack.pop();
137
+            } else {
138
+                qDebug() << "Mismatched parentheses detected in expression!";
139
+            }
140
+        } else {
141
+            // token is an operator
142
+            while (!operatorStack.isEmpty()
143
+                   && operatorStack.top().operatorPrecedence <= token.operatorPrecedence
144
+                   && operatorStack.top().value != "(") {
145
+                output.append(operatorStack.pop());
146
+            }
147
+            operatorStack.push(token);
148
+        }
149
+    }
150
+
151
+    while (!operatorStack.isEmpty()) {
152
+        if (operatorStack.top().value == "(" || operatorStack.top().value == ")") {
153
+            qDebug() << "Mismatched parentheses detected in expression!";
154
+        } else {
155
+            output.append(operatorStack.pop());
156
+        }
157
+    }
158
+
159
+    return output;
160
+}
161
+
162
+// Evaluate postfix expression.
163
+// https://en.wikipedia.org/wiki/Reverse_Polish_notation#Postfix_evaluation_algorithm
164
+int ParseUtil::evaluatePostfix(QList<Token> postfix) {
165
+    QStack<Token> stack;
166
+    for (Token token : postfix) {
167
+        if (token.type == TokenType::Operator) {
168
+            int op2 = stack.pop().value.toInt(nullptr, 0);
169
+            int op1 = stack.pop().value.toInt(nullptr, 0);
170
+            int result = 0;
171
+            if (token.value == "*") {
172
+                result = op1 * op2;
173
+            } else if (token.value == "/") {
174
+                result = op1 / op2;
175
+            } else if (token.value == "+") {
176
+                result = op1 + op2;
177
+            } else if (token.value == "-") {
178
+                result = op1 - op2;
179
+            } else if (token.value == "<<") {
180
+                result = op1 << op2;
181
+            } else if (token.value == ">>") {
182
+                result = op1 >> op2;
183
+            } else if (token.value == "&") {
184
+                result = op1 & op2;
185
+            } else if (token.value == "^") {
186
+                result = op1 ^ op2;
187
+            } else if (token.value == "|") {
188
+                result = op1 | op2;
189
+            } else {
190
+                qDebug() << "Unsupported postfix operator: " << token.value;
191
+            }
192
+            stack.push(Token(QString("%1").arg(result), "decimal"));
193
+        } else {
194
+            stack.push(token);
195
+        }
196
+    }
197
+
198
+    return stack.pop().value.toInt(nullptr, 0);
199
+}

+ 43
- 0
parseutil.h Целия файл

@@ -0,0 +1,43 @@
1
+#ifndef PARSEUTIL_H
2
+#define PARSEUTIL_H
3
+
4
+#include <QString>
5
+#include <QList>
6
+
7
+enum TokenType {
8
+    Number,
9
+    Operator,
10
+};
11
+
12
+class Token {
13
+public:
14
+    Token(QString value = "", QString type = "") {
15
+        this->value = value;
16
+        this->type = TokenType::Operator;
17
+        if (type == "decimal" || type == "hex") {
18
+            this->type = TokenType::Number;
19
+            this->operatorPrecedence = -1;
20
+        } else if (type == "operator") {
21
+            this->operatorPrecedence = precedenceMap[value];
22
+        }
23
+    }
24
+    static QMap<QString, int> precedenceMap;
25
+    QString value;
26
+    TokenType type;
27
+    int operatorPrecedence; // only relevant for operator tokens
28
+};
29
+
30
+class ParseUtil
31
+{
32
+public:
33
+    ParseUtil();
34
+    void strip_comment(QString*);
35
+    QList<QStringList>* parseAsm(QString);
36
+    int evaluateDefine(QString, QMap<QString, int>*);
37
+private:
38
+    QList<Token> tokenizeExpression(QString expression, QMap<QString, int>* knownIdentifiers);
39
+    QList<Token> generatePostfix(QList<Token> tokens);
40
+    int evaluatePostfix(QList<Token> postfix);
41
+};
42
+
43
+#endif // PARSEUTIL_H

+ 4
- 4
pretmap.pro Целия файл

@@ -15,7 +15,6 @@ TEMPLATE = app
15 15
 SOURCES += main.cpp\
16 16
         mainwindow.cpp \
17 17
     project.cpp \
18
-    asm.cpp \
19 18
     map.cpp \
20 19
     blockdata.cpp \
21 20
     block.cpp \
@@ -25,11 +24,11 @@ SOURCES += main.cpp\
25 24
     event.cpp \
26 25
     editor.cpp \
27 26
     objectpropertiesframe.cpp \
28
-    graphicsview.cpp
27
+    graphicsview.cpp \
28
+    parseutil.cpp
29 29
 
30 30
 HEADERS  += mainwindow.h \
31 31
     project.h \
32
-    asm.h \
33 32
     map.h \
34 33
     blockdata.h \
35 34
     block.h \
@@ -39,7 +38,8 @@ HEADERS  += mainwindow.h \
39 38
     event.h \
40 39
     editor.h \
41 40
     objectpropertiesframe.h \
42
-    graphicsview.h
41
+    graphicsview.h \
42
+    parseutil.h
43 43
 
44 44
 FORMS    += mainwindow.ui \
45 45
     objectpropertiesframe.ui

+ 78
- 66
project.cpp Целия файл

@@ -1,4 +1,4 @@
1
-#include "asm.h"
1
+#include "parseutil.h"
2 2
 #include "project.h"
3 3
 #include "tile.h"
4 4
 #include "tileset.h"
@@ -18,6 +18,9 @@ Project::Project()
18 18
     groupNames = new QStringList;
19 19
     map_groups = new QMap<QString, int>;
20 20
     mapNames = new QStringList;
21
+    itemNames = new QStringList;
22
+    flagNames = new QStringList;
23
+    varNames = new QStringList;
21 24
     map_cache = new QMap<QString, Map*>;
22 25
     mapConstantsToMapNames = new QMap<QString, QString>;
23 26
     mapNamesToMapConstants = new QMap<QString, QString>;
@@ -68,7 +71,7 @@ void Project::loadMapConnections(Map *map) {
68 71
         QString path = root + QString("/data/maps/%1/connections.inc").arg(map->name);
69 72
         QString text = readTextFile(path);
70 73
         if (!text.isNull()) {
71
-            QList<QStringList> *commands = parse(text);
74
+            QList<QStringList> *commands = parseAsm(text);
72 75
             QStringList *list = getLabelValues(commands, map->connections_label);
73 76
 
74 77
             //// Avoid using this value. It ought to be generated instead.
@@ -147,13 +150,13 @@ void Project::readMapHeader(Map* map) {
147 150
     }
148 151
 
149 152
     QString label = map->name;
150
-    Asm *parser = new Asm;
153
+    ParseUtil *parser = new ParseUtil;
151 154
 
152 155
     QString header_text = readTextFile(root + "/data/maps/" + label + "/header.inc");
153 156
     if (header_text.isNull()) {
154 157
         return;
155 158
     }
156
-    QStringList *header = getLabelValues(parser->parse(header_text), label);
159
+    QStringList *header = getLabelValues(parser->parseAsm(header_text), label);
157 160
     map->attributes_label = header->value(0);
158 161
     map->events_label = header->value(1);
159 162
     map->scripts_label = header->value(2);
@@ -209,7 +212,7 @@ void Project::saveMapHeader(Map *map) {
209 212
 void Project::readMapAttributesTable() {
210 213
     int curMapIndex = 1;
211 214
     QString attributesText = readTextFile(getMapAttributesTableFilepath());
212
-    QList<QStringList>* values = parse(attributesText);
215
+    QList<QStringList>* values = parseAsm(attributesText);
213 216
     bool inAttributePointers = false;
214 217
     for (int i = 0; i < values->length(); i++) {
215 218
         QStringList params = values->value(i);
@@ -262,13 +265,13 @@ void Project::readMapAttributes(Map* map) {
262 265
         return;
263 266
     }
264 267
 
265
-    Asm *parser = new Asm;
268
+    ParseUtil *parser = new ParseUtil;
266 269
 
267 270
     QString assets_text = readTextFile(getMapAssetsFilepath());
268 271
     if (assets_text.isNull()) {
269 272
         return;
270 273
     }
271
-    QStringList *attributes = getLabelValues(parser->parse(assets_text), map->attributes_label);
274
+    QStringList *attributes = getLabelValues(parser->parseAsm(assets_text), map->attributes_label);
272 275
     map->width = attributes->value(0);
273 276
     map->height = attributes->value(1);
274 277
     map->border_label = attributes->value(2);
@@ -280,13 +283,13 @@ void Project::readMapAttributes(Map* map) {
280 283
 void Project::readAllMapAttributes() {
281 284
     mapAttributes.clear();
282 285
 
283
-    Asm *parser = new Asm;
286
+    ParseUtil *parser = new ParseUtil;
284 287
     QString assets_text = readTextFile(getMapAssetsFilepath());
285 288
     if (assets_text.isNull()) {
286 289
         return;
287 290
     }
288 291
 
289
-    QList<QStringList> *commands = parser->parse(assets_text);
292
+    QList<QStringList> *commands = parser->parseAsm(assets_text);
290 293
 
291 294
     // Assume the _assets.inc file is grouped consistently in the order of:
292 295
     // 1. <map_name>_MapBorder
@@ -536,10 +539,10 @@ void Project::getTilesets(Map* map) {
536 539
 }
537 540
 
538 541
 Tileset* Project::loadTileset(QString label) {
539
-    Asm *parser = new Asm;
542
+    ParseUtil *parser = new ParseUtil;
540 543
 
541 544
     QString headers_text = readTextFile(root + "/data/tilesets/headers.inc");
542
-    QStringList *values = getLabelValues(parser->parse(headers_text), label);
545
+    QStringList *values = getLabelValues(parser->parseAsm(headers_text), label);
543 546
     Tileset *tileset = new Tileset;
544 547
     tileset->name = label;
545 548
     tileset->is_compressed = values->value(0);
@@ -559,7 +562,7 @@ Tileset* Project::loadTileset(QString label) {
559 562
 
560 563
 QString Project::getBlockdataPath(Map* map) {
561 564
     QString text = readTextFile(getMapAssetsFilepath());
562
-    QStringList *values = getLabelValues(parse(text), map->blockdata_label);
565
+    QStringList *values = getLabelValues(parseAsm(text), map->blockdata_label);
563 566
     QString path;
564 567
     if (!values->isEmpty()) {
565 568
         path = root + "/" + values->value(0).section('"', 1, 1);
@@ -571,7 +574,7 @@ QString Project::getBlockdataPath(Map* map) {
571 574
 
572 575
 QString Project::getMapBorderPath(Map *map) {
573 576
     QString text = readTextFile(getMapAssetsFilepath());
574
-    QStringList *values = getLabelValues(parse(text), map->border_label);
577
+    QStringList *values = getLabelValues(parseAsm(text), map->border_label);
575 578
     QString path;
576 579
     if (!values->isEmpty()) {
577 580
         path = root + "/" + values->value(0).section('"', 1, 1);
@@ -702,7 +705,7 @@ void Project::saveAllDataStructures() {
702 705
 }
703 706
 
704 707
 void Project::loadTilesetAssets(Tileset* tileset) {
705
-    Asm* parser = new Asm;
708
+    ParseUtil* parser = new ParseUtil;
706 709
     QString category = (tileset->is_secondary == "TRUE") ? "secondary" : "primary";
707 710
     if (tileset->name.isNull()) {
708 711
         return;
@@ -710,7 +713,7 @@ void Project::loadTilesetAssets(Tileset* tileset) {
710 713
     QString dir_path = root + "/data/tilesets/" + category + "/" + tileset->name.replace("gTileset_", "").toLower();
711 714
 
712 715
     QString graphics_text = readTextFile(root + "/data/tilesets/graphics.inc");
713
-    QList<QStringList> *graphics = parser->parse(graphics_text);
716
+    QList<QStringList> *graphics = parser->parseAsm(graphics_text);
714 717
     QStringList *tiles_values = getLabelValues(graphics, tileset->tiles_label);
715 718
     QStringList *palettes_values = getLabelValues(graphics, tileset->palettes_label);
716 719
 
@@ -740,7 +743,7 @@ void Project::loadTilesetAssets(Tileset* tileset) {
740 743
     QString metatiles_path;
741 744
     QString metatile_attrs_path;
742 745
     QString metatiles_text = readTextFile(root + "/data/tilesets/metatiles.inc");
743
-    QList<QStringList> *metatiles_macros = parser->parse(metatiles_text);
746
+    QList<QStringList> *metatiles_macros = parser->parseAsm(metatiles_text);
744 747
     QStringList *metatiles_values = getLabelValues(metatiles_macros, tileset->metatiles_label);
745 748
     if (!metatiles_values->isEmpty()) {
746 749
         metatiles_path = root + "/" + metatiles_values->value(0).section('"', 1, 1);
@@ -915,8 +918,8 @@ void Project::readMapGroups() {
915 918
     if (text.isNull()) {
916 919
         return;
917 920
     }
918
-    Asm *parser = new Asm;
919
-    QList<QStringList> *commands = parser->parse(text);
921
+    ParseUtil *parser = new ParseUtil;
922
+    QList<QStringList> *commands = parser->parseAsm(text);
920 923
 
921 924
     bool in_group_pointers = false;
922 925
     QStringList *groups = new QStringList;
@@ -1012,9 +1015,9 @@ QString Project::getNewMapName() {
1012 1015
     return newMapName;
1013 1016
 }
1014 1017
 
1015
-QList<QStringList>* Project::parse(QString text) {
1016
-    Asm *parser = new Asm;
1017
-    return parser->parse(text);
1018
+QList<QStringList>* Project::parseAsm(QString text) {
1019
+    ParseUtil *parser = new ParseUtil;
1020
+    return parser->parseAsm(text);
1018 1021
 }
1019 1022
 
1020 1023
 QStringList Project::getLocations() {
@@ -1062,36 +1065,49 @@ QStringList Project::getBattleScenes() {
1062 1065
     return names;
1063 1066
 }
1064 1067
 
1065
-QStringList Project::getSongNames() {
1066
-    QStringList names;
1067
-    QString text = readTextFile(root + "/include/constants/songs.h");
1068
+void Project::readItemNames() {
1069
+    QString filepath = root + "/include/constants/items.h";
1070
+    QStringList prefixes = (QStringList() << "ITEM_");
1071
+    readCDefinesSorted(filepath, prefixes, itemNames);
1072
+}
1073
+
1074
+void Project::readFlagNames() {
1075
+    QString filepath = root + "/include/constants/flags.h";
1076
+    QStringList prefixes = (QStringList() << "FLAG_");
1077
+    readCDefinesSorted(filepath, prefixes, flagNames);
1078
+}
1079
+
1080
+void Project::readVarNames() {
1081
+    QString filepath = root + "/include/constants/vars.h";
1082
+    QStringList prefixes = (QStringList() << "VAR_");
1083
+    readCDefinesSorted(filepath, prefixes, varNames);
1084
+}
1085
+
1086
+void Project::readCDefinesSorted(QString filepath, QStringList prefixes, QStringList* definesToSet) {
1087
+    QString text = readTextFile(filepath);
1068 1088
     if (!text.isNull()) {
1069
-        QStringList songDefinePrefixes;
1070
-        songDefinePrefixes << "SE_" << "BGM_";
1071
-        QMap<QString, int> songDefines = readCDefines(text, songDefinePrefixes);
1072
-        names = songDefines.keys();
1089
+        QMap<QString, int> defines = readCDefines(text, prefixes);
1090
+
1091
+        // The defines should to be sorted by their underlying value, not alphabetically.
1092
+        // Reverse the map and read out the resulting keys in order.
1093
+        QMultiMap<int, QString> definesInverse;
1094
+        for (QString defineName : defines.keys()) {
1095
+            definesInverse.insert(defines[defineName], defineName);
1096
+        }
1097
+        *definesToSet = definesInverse.values();
1073 1098
     }
1074
-    return names;
1075 1099
 }
1076 1100
 
1077
-QString Project::getSongName(int songNumber) {
1101
+QStringList Project::getSongNames() {
1078 1102
     QStringList names;
1079 1103
     QString text = readTextFile(root + "/include/constants/songs.h");
1080 1104
     if (!text.isNull()) {
1081 1105
         QStringList songDefinePrefixes;
1082 1106
         songDefinePrefixes << "SE_" << "BGM_";
1083 1107
         QMap<QString, int> songDefines = readCDefines(text, songDefinePrefixes);
1084
-
1085
-        // Loop through song defines, and fine the one with the matching song number.
1086
-        QMap<QString, int>::iterator iter = songDefines.begin();
1087
-        while (iter != songDefines.end()) {
1088
-            if (iter.value() == songNumber) {
1089
-                return iter.key();
1090
-            }
1091
-            iter++;
1092
-        }
1108
+        names = songDefines.keys();
1093 1109
     }
1094
-    return "";
1110
+    return names;
1095 1111
 }
1096 1112
 
1097 1113
 QMap<QString, int> Project::getMapObjGfxConstants() {
@@ -1128,7 +1144,7 @@ void Project::loadObjectPixmaps(QList<Event*> objects) {
1128 1144
     QString pointers_text = readTextFile(root + "/src/data/field_map_obj/map_object_graphics_info_pointers.h");
1129 1145
     QString info_text = readTextFile(root + "/src/data/field_map_obj/map_object_graphics_info.h");
1130 1146
     QString pic_text = readTextFile(root + "/src/data/field_map_obj/map_object_pic_tables.h");
1131
-    QString assets_text = readTextFile(root + "/src/field/field_map_obj.c");
1147
+    QString assets_text = readTextFile(root + "/src/field/event_object_movement.c");
1132 1148
 
1133 1149
     QStringList pointers = readCArray(pointers_text, "gMapObjectGraphicsInfoPointers");
1134 1150
 
@@ -1228,8 +1244,8 @@ void Project::saveMapEvents(Map *map) {
1228 1244
             text += QString(", %1").arg(coords->get("y"));
1229 1245
             text += QString(", %1").arg(coords->get("elevation"));
1230 1246
             text += QString(", 0");
1231
-            text += QString(", %1").arg(coords->get("coord_unknown1"));
1232
-            text += QString(", %1").arg(coords->get("coord_unknown2"));
1247
+            text += QString(", %1").arg(coords->get("script_var"));
1248
+            text += QString(", %1").arg(coords->get("script_var_value"));
1233 1249
             text += QString(", 0");
1234 1250
             text += QString(", %1").arg(coords->get("script_label"));
1235 1251
             text += "\n";
@@ -1298,13 +1314,13 @@ void Project::readMapEvents(Map *map) {
1298 1314
         return;
1299 1315
     }
1300 1316
 
1301
-    QStringList *labels = getLabelValues(parse(text), map->events_label);
1317
+    QStringList *labels = getLabelValues(parseAsm(text), map->events_label);
1302 1318
     map->object_events_label = labels->value(0);
1303 1319
     map->warps_label = labels->value(1);
1304 1320
     map->coord_events_label = labels->value(2);
1305 1321
     map->bg_events_label = labels->value(3);
1306 1322
 
1307
-    QList<QStringList> *object_events = getLabelMacros(parse(text), map->object_events_label);
1323
+    QList<QStringList> *object_events = getLabelMacros(parseAsm(text), map->object_events_label);
1308 1324
     map->events["object"].clear();
1309 1325
     for (QStringList command : *object_events) {
1310 1326
         if (command.value(0) == "object_event") {
@@ -1348,7 +1364,7 @@ void Project::readMapEvents(Map *map) {
1348 1364
         }
1349 1365
     }
1350 1366
 
1351
-    QList<QStringList> *warps = getLabelMacros(parse(text), map->warps_label);
1367
+    QList<QStringList> *warps = getLabelMacros(parseAsm(text), map->warps_label);
1352 1368
     map->events["warp"].clear();
1353 1369
     for (QStringList command : *warps) {
1354 1370
         if (command.value(0) == "warp_def") {
@@ -1372,7 +1388,7 @@ void Project::readMapEvents(Map *map) {
1372 1388
         }
1373 1389
     }
1374 1390
 
1375
-    QList<QStringList> *coords = getLabelMacros(parse(text), map->coord_events_label);
1391
+    QList<QStringList> *coords = getLabelMacros(parseAsm(text), map->coord_events_label);
1376 1392
     map->events["trap"].clear();
1377 1393
     map->events["trap_weather"].clear();
1378 1394
     for (QStringList command : *coords) {
@@ -1389,8 +1405,8 @@ void Project::readMapEvents(Map *map) {
1389 1405
             coord->put("x", command.value(i++));
1390 1406
             coord->put("y", command.value(i++));
1391 1407
             coord->put("elevation", command.value(i++));
1392
-            coord->put("coord_unknown1", command.value(i++));
1393
-            coord->put("coord_unknown2", command.value(i++));
1408
+            coord->put("script_var", command.value(i++));
1409
+            coord->put("script_var_value", command.value(i++));
1394 1410
             coord->put("script_label", command.value(i++));
1395 1411
             //coord_unknown3
1396 1412
             //coord_unknown4
@@ -1410,7 +1426,7 @@ void Project::readMapEvents(Map *map) {
1410 1426
         }
1411 1427
     }
1412 1428
 
1413
-    QList<QStringList> *bgs = getLabelMacros(parse(text), map->bg_events_label);
1429
+    QList<QStringList> *bgs = getLabelMacros(parseAsm(text), map->bg_events_label);
1414 1430
     map->events["sign"].clear();
1415 1431
     map->events["event_hidden_item"].clear();
1416 1432
     map->events["event_secret_base"].clear();
@@ -1515,27 +1531,23 @@ QString Project::readCIncbin(QString text, QString label) {
1515 1531
 }
1516 1532
 
1517 1533
 QMap<QString, int> Project::readCDefines(QString text, QStringList prefixes) {
1518
-    QMap<QString, int> defines;
1519
-
1520
-    QString combinedPrefixes = "[" + prefixes.join('|') + "]";
1521
-    QRegularExpression re(QString("#define\\s+(?<defineName>%1\\w+)\\s(?<defineValue>\\w+)").arg(combinedPrefixes));
1534
+    ParseUtil parser;
1535
+    QMap<QString, int> allDefines;
1536
+    QMap<QString, int> filteredDefines;
1537
+    QRegularExpression re("#define\\s+(?<defineName>\\w+)[^\\S\\n]+(?<defineValue>.+)");
1522 1538
     QRegularExpressionMatchIterator iter = re.globalMatch(text);
1523 1539
     while (iter.hasNext()) {
1524 1540
         QRegularExpressionMatch match = iter.next();
1525 1541
         QString name = match.captured("defineName");
1526
-        QString value = match.captured("defineValue");
1527
-        bool valid;
1528
-        int parsedValue = value.startsWith("0x") ? value.toInt(&valid, 16) : value.toInt(&valid, 10);
1529
-        if (valid) {
1530
-            if (!defines.contains(name)) {
1531
-                defines.insert(name, parsedValue);
1532
-            } else {
1533
-                qDebug() << QString("Define '%1' is defined multiple times'").arg(name);
1542
+        QString expression = match.captured("defineValue");
1543
+        expression.replace(QRegularExpression("//.*"), "");
1544
+        int value = parser.evaluateDefine(expression, &allDefines);
1545
+        allDefines.insert(name, value);
1546
+        for (QString prefix : prefixes) {
1547
+            if (name.startsWith(prefix)) {
1548
+                filteredDefines.insert(name, value);
1534 1549
             }
1535
-        } else {
1536
-            qDebug() << QString("Failed to parse define '%1' value '%2' as base 10 or hexadecimal value").arg(name, value);
1537 1550
         }
1538 1551
     }
1539
-
1540
-    return defines;
1552
+    return filteredDefines;
1541 1553
 }

+ 9
- 3
project.h Целия файл

@@ -23,7 +23,9 @@ public:
23 23
     QMap<int, QString> mapAttributesTableMaster;
24 24
     QMap<QString, QMap<QString, QString>> mapAttributes;
25 25
     QMap<QString, QMap<QString, QString>> mapAttributesMaster;
26
-
26
+    QStringList *itemNames = NULL;
27
+    QStringList *flagNames = NULL;
28
+    QStringList *varNames = NULL;
27 29
 
28 30
     QMap<QString, Map*> *map_cache;
29 31
     Map* loadMap(QString);
@@ -65,14 +67,16 @@ public:
65 67
     void saveMapGroupsTable();
66 68
     void saveMapConstantsHeader();
67 69
 
68
-    QList<QStringList>* parse(QString text);
70
+    QList<QStringList>* parseAsm(QString text);
69 71
     QStringList getSongNames();
70
-    QString getSongName(int);
71 72
     QStringList getLocations();
72 73
     QStringList getVisibilities();
73 74
     QStringList getWeathers();
74 75
     QStringList getMapTypes();
75 76
     QStringList getBattleScenes();
77
+    void readItemNames();
78
+    void readFlagNames();
79
+    void readVarNames();
76 80
 
77 81
     void loadObjectPixmaps(QList<Event*> objects);
78 82
     QMap<QString, int> getMapObjGfxConstants();
@@ -95,6 +99,8 @@ private:
95 99
     void saveMapHeader(Map*);
96 100
     void saveMapAttributesTable();
97 101
     void updateMapAttributes(Map* map);
102
+    void readCDefinesSorted(QString, QStringList, QStringList*);
103
+    void readCDefinesSorted(QString, QStringList, QStringList*, QString, int);
98 104
 
99 105
     void setNewMapHeader(Map* map, int mapIndex);
100 106
     void setNewMapAttributes(Map* map);