diff --git a/include/asm/symbol.hpp b/include/asm/symbol.hpp index 19280a35..2a1c5e19 100644 --- a/include/asm/symbol.hpp +++ b/include/asm/symbol.hpp @@ -68,7 +68,7 @@ struct Symbol { uint32_t getConstantValue() const; }; -void sym_ForEach(void (*func)(Symbol &)); +void sym_ForEach(void (*callback)(Symbol &)); void sym_SetExportAll(bool set); Symbol *sym_AddLocalLabel(std::string const &symName); diff --git a/include/link/symbol.hpp b/include/link/symbol.hpp index cbb436da..392b88c8 100644 --- a/include/link/symbol.hpp +++ b/include/link/symbol.hpp @@ -38,6 +38,8 @@ struct Symbol { Label const &label() const; }; +void sym_ForEach(void (*callback)(Symbol &)); + void sym_AddSymbol(Symbol &symbol); /* diff --git a/man/rgblink.1 b/man/rgblink.1 index afd3e64d..e3c8e55c 100644 --- a/man/rgblink.1 +++ b/man/rgblink.1 @@ -78,7 +78,9 @@ If specified, the map file will not list symbols, only sections. .It Fl m Ar map_file , Fl \-map Ar map_file Write a map file to the given filename, listing how sections and symbols were assigned. .It Fl n Ar sym_file , Fl \-sym Ar sym_file -Write a symbol file to the given filename, listing the address of all exported symbols. +Write a symbol file to the given filename, listing all visible labels and exported numeric constants. +Labels output their bank and address, numeric constants output their value, following +.Lk https://rgbds.gbdev.io/sym/ this specification . Several external programs can use this information, for example to help debugging ROMs. .It Fl O Ar overlay_file , Fl \-overlay Ar overlay_file If specified, sections will be overlaid "on top" of the ROM image diff --git a/src/link/output.cpp b/src/link/output.cpp index b1e985e5..4a8de4a7 100644 --- a/src/link/output.cpp +++ b/src/link/output.cpp @@ -558,6 +558,25 @@ static void writeSym() { for (uint32_t bank = 0; bank < sections[type].size(); bank++) writeSymBank(sections[type][bank], type, bank); } + + // Output the exported numeric constants + static std::vector constants; // `static` so `sym_ForEach` callback can see it + constants.clear(); + sym_ForEach([](Symbol &sym) { + // Symbols are already limited to the exported ones + if (std::holds_alternative(sym.data)) + constants.push_back(&sym); + }); + // Numeric constants are ordered by value, then by name + std::sort(RANGE(constants), [](Symbol *sym1, Symbol *sym2) -> bool { + int32_t val1 = std::get(sym1->data), val2 = std::get(sym2->data); + return val1 != val2 ? val1 < val2 : sym1->name < sym2->name; + }); + for (Symbol *sym : constants) { + int32_t val = std::get(sym->data); + int width = val < 0x100 ? 2 : val < 0x10000 ? 4 : 8; + fprintf(symFile, "%0*" PRIx32 " %s\n", width, val, sym->name.c_str()); + } } // Writes the map file, if applicable. diff --git a/src/link/symbol.cpp b/src/link/symbol.cpp index f061938b..1aadd329 100644 --- a/src/link/symbol.cpp +++ b/src/link/symbol.cpp @@ -22,6 +22,11 @@ Label const &Symbol::label() const { return std::get