mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Extend RGBASM and RGBLINK verbosity flags to have multiple levels like RGBGFX (#1772)
This commit is contained in:
@@ -14,6 +14,7 @@
|
||||
#include "itertools.hpp"
|
||||
#include "linkdefs.hpp"
|
||||
#include "platform.hpp"
|
||||
#include "verbosity.hpp"
|
||||
|
||||
#include "link/main.hpp"
|
||||
#include "link/output.hpp"
|
||||
@@ -405,7 +406,7 @@ static std::vector<Section const *> checkOverlayCompat() {
|
||||
}
|
||||
|
||||
void assign_AssignSections() {
|
||||
verbosePrint("Beginning assignment...\n");
|
||||
verbosePrint(VERB_NOTICE, "Beginning assignment...\n");
|
||||
|
||||
// Initialize assignment
|
||||
initFreeSpace();
|
||||
@@ -443,7 +444,7 @@ void assign_AssignSections() {
|
||||
// Assign sections in decreasing constraint order
|
||||
for (uint8_t constraints = std::size(unassignedSections); constraints--;) {
|
||||
if (char const *constraintName = constraintNames[constraints]; constraintName) {
|
||||
verbosePrint("Assigning %sconstrained sections...\n", constraintName);
|
||||
verbosePrint(VERB_INFO, "Assigning %sconstrained sections...\n", constraintName);
|
||||
} else {
|
||||
assume(unassignedSections[constraints].empty());
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@
|
||||
#include "script.hpp" // Generated from script.y
|
||||
#include "usage.hpp"
|
||||
#include "util.hpp" // UpperMap, printChar
|
||||
#include "verbosity.hpp"
|
||||
#include "version.hpp"
|
||||
|
||||
#include "link/assign.hpp"
|
||||
@@ -31,28 +32,7 @@
|
||||
|
||||
Options options;
|
||||
|
||||
std::string const &FileStackNode::dump(uint32_t curLineNo) const {
|
||||
if (std::holds_alternative<std::vector<uint32_t>>(data)) {
|
||||
assume(parent); // REPT nodes use their parent's name
|
||||
std::string const &lastName = parent->dump(lineNo);
|
||||
fputs(" -> ", stderr);
|
||||
fputs(lastName.c_str(), stderr);
|
||||
for (uint32_t iter : iters()) {
|
||||
fprintf(stderr, "::REPT~%" PRIu32, iter);
|
||||
}
|
||||
fprintf(stderr, "(%" PRIu32 ")", curLineNo);
|
||||
return lastName;
|
||||
} else {
|
||||
if (parent) {
|
||||
parent->dump(lineNo);
|
||||
fputs(" -> ", stderr);
|
||||
}
|
||||
std::string const &nodeName = name();
|
||||
fputs(nodeName.c_str(), stderr);
|
||||
fprintf(stderr, "(%" PRIu32 ")", curLineNo);
|
||||
return nodeName;
|
||||
}
|
||||
}
|
||||
static char const *linkerScriptName = nullptr; // -l
|
||||
|
||||
// Short options
|
||||
static char const *optstring = "dhl:m:Mn:O:o:p:S:tVvW:wx";
|
||||
@@ -96,18 +76,131 @@ static Usage usage(
|
||||
" -o, --output <path> set the output file\n"
|
||||
" -p, --pad <value> set the value to pad between sections with\n"
|
||||
" -x, --nopad disable padding of output binary\n"
|
||||
" -V, --version print RGBLINK version and exits\n"
|
||||
" -V, --version print RGBLINK version and exit\n"
|
||||
" -W, --warning <warning> enable or disable warnings\n"
|
||||
"\n"
|
||||
"For help, use `man rgblink' or go to https://rgbds.gbdev.io/docs/\n"
|
||||
);
|
||||
// clang-format on
|
||||
|
||||
static void parseScrambleSpec(char *spec) {
|
||||
static UpperMap<std::pair<uint16_t *, uint16_t>> scrambleSpecs{
|
||||
{"ROMX", std::pair{&options.scrambleROMX, 65535}},
|
||||
{"SRAM", std::pair{&options.scrambleSRAM, 255} },
|
||||
{"WRAMX", std::pair{&options.scrambleWRAMX, 7} },
|
||||
// LCOV_EXCL_START
|
||||
static void verboseOutputConfig(int argc, char *argv[]) {
|
||||
if (!checkVerbosity(VERB_CONFIG)) {
|
||||
return;
|
||||
}
|
||||
|
||||
fprintf(stderr, "rgblink %s\n", get_package_version_string());
|
||||
|
||||
printVVVVVVerbosity();
|
||||
|
||||
fputs("Options:\n", stderr);
|
||||
// -d/--dmg
|
||||
if (options.isDmgMode) {
|
||||
fputs("\tDMG mode prohibits non-DMG section types\n", stderr);
|
||||
}
|
||||
// -t/--tiny
|
||||
if (options.is32kMode) {
|
||||
fputs("\tROM0 covers the full 32 KiB of ROM\n", stderr);
|
||||
}
|
||||
// -w/--wramx
|
||||
if (options.isWRAM0Mode) {
|
||||
fputs("\tWRAM0 covers the full 8 KiB of WRAM\n", stderr);
|
||||
}
|
||||
// -x/--nopad
|
||||
if (options.disablePadding) {
|
||||
fputs("\tNo padding at the end of the ROM file\n", stderr);
|
||||
}
|
||||
// -p/--pad
|
||||
fprintf(stderr, "\tPad value: 0x%02" PRIx8 "\n", options.padValue);
|
||||
// -S/--scramble
|
||||
if (options.scrambleROMX || options.scrambleWRAMX || options.scrambleSRAM) {
|
||||
fputs("\tScramble: ", stderr);
|
||||
if (options.scrambleROMX) {
|
||||
fprintf(stderr, "ROMX = %" PRIu16, options.scrambleROMX);
|
||||
if (options.scrambleWRAMX || options.scrambleSRAM) {
|
||||
fputs(", ", stderr);
|
||||
}
|
||||
}
|
||||
if (options.scrambleWRAMX) {
|
||||
fprintf(stderr, "WRAMX = %" PRIu16, options.scrambleWRAMX);
|
||||
if (options.scrambleSRAM) {
|
||||
fputs(", ", stderr);
|
||||
}
|
||||
}
|
||||
if (options.scrambleSRAM) {
|
||||
fprintf(stderr, "SRAM = %" PRIu16, options.scrambleSRAM);
|
||||
}
|
||||
putc('\n', stderr);
|
||||
}
|
||||
// file ...
|
||||
if (musl_optind < argc) {
|
||||
fprintf(stderr, "\tInput object files: ");
|
||||
for (int i = musl_optind; i < argc; ++i) {
|
||||
if (i > musl_optind) {
|
||||
fputs(", ", stderr);
|
||||
}
|
||||
if (i - musl_optind == 10) {
|
||||
fprintf(stderr, "and %d more", argc - i);
|
||||
break;
|
||||
}
|
||||
fputs(argv[i], stderr);
|
||||
}
|
||||
putc('\n', stderr);
|
||||
}
|
||||
auto printPath = [](char const *name, char const *path) {
|
||||
if (path) {
|
||||
fprintf(stderr, "\t%s: %s\n", name, path);
|
||||
}
|
||||
};
|
||||
// -O/--overlay
|
||||
printPath("Overlay file", options.overlayFileName);
|
||||
// -l/--linkerscript
|
||||
printPath("Linker script", linkerScriptName);
|
||||
// -o/--output
|
||||
printPath("Output ROM file", options.outputFileName);
|
||||
// -m/--map
|
||||
printPath("Output map file", options.mapFileName);
|
||||
// -M/--no-sym-in-map
|
||||
if (options.mapFileName && options.noSymInMap) {
|
||||
fputs("\tNo symbols in map file\n", stderr);
|
||||
}
|
||||
// -n/--sym
|
||||
printPath("Output sym file", options.symFileName);
|
||||
fputs("Ready.\n", stderr);
|
||||
}
|
||||
// LCOV_EXCL_STOP
|
||||
|
||||
std::string const &FileStackNode::dump(uint32_t curLineNo) const {
|
||||
if (std::holds_alternative<std::vector<uint32_t>>(data)) {
|
||||
assume(parent); // REPT nodes use their parent's name
|
||||
std::string const &lastName = parent->dump(lineNo);
|
||||
fputs(" -> ", stderr);
|
||||
fputs(lastName.c_str(), stderr);
|
||||
for (uint32_t iter : iters()) {
|
||||
fprintf(stderr, "::REPT~%" PRIu32, iter);
|
||||
}
|
||||
fprintf(stderr, "(%" PRIu32 ")", curLineNo);
|
||||
return lastName;
|
||||
} else {
|
||||
if (parent) {
|
||||
parent->dump(lineNo);
|
||||
fputs(" -> ", stderr);
|
||||
}
|
||||
std::string const &nodeName = name();
|
||||
fputs(nodeName.c_str(), stderr);
|
||||
fprintf(stderr, "(%" PRIu32 ")", curLineNo);
|
||||
return nodeName;
|
||||
}
|
||||
}
|
||||
|
||||
static void parseScrambleSpec(char *spec) {
|
||||
// clang-format off: vertically align nested initializers
|
||||
static UpperMap<std::pair<uint16_t *, uint16_t>> scrambleSpecs{
|
||||
{"ROMX", std::pair{&options.scrambleROMX, 65535}},
|
||||
{"SRAM", std::pair{&options.scrambleSRAM, 255 }},
|
||||
{"WRAMX", std::pair{&options.scrambleWRAMX, 7 }},
|
||||
};
|
||||
// clang-format on
|
||||
|
||||
// Skip leading whitespace before the regions.
|
||||
spec += strspn(spec, " \t");
|
||||
@@ -211,8 +304,6 @@ static void parseScrambleSpec(char *spec) {
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[]) {
|
||||
char const *linkerScriptName = nullptr; // -l
|
||||
|
||||
// Parse options
|
||||
for (int ch; (ch = musl_getopt_long_only(argc, argv, optstring, longopts, nullptr)) != -1;) {
|
||||
switch (ch) {
|
||||
@@ -283,7 +374,7 @@ int main(int argc, char *argv[]) {
|
||||
// LCOV_EXCL_STOP
|
||||
case 'v':
|
||||
// LCOV_EXCL_START
|
||||
options.beVerbose = true;
|
||||
incrementVerbosity();
|
||||
break;
|
||||
// LCOV_EXCL_STOP
|
||||
case 'W':
|
||||
@@ -302,10 +393,10 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
}
|
||||
|
||||
int curArgIndex = musl_optind;
|
||||
verboseOutputConfig(argc, argv);
|
||||
|
||||
// If no input files were specified, the user must have screwed up
|
||||
if (curArgIndex == argc) {
|
||||
if (musl_optind == argc) {
|
||||
usage.printAndExit("Please specify an input file (pass `-` to read from standard input)");
|
||||
}
|
||||
|
||||
@@ -323,13 +414,14 @@ int main(int argc, char *argv[]) {
|
||||
}
|
||||
|
||||
// Read all object files first,
|
||||
for (obj_Setup(argc - curArgIndex); curArgIndex < argc; ++curArgIndex) {
|
||||
obj_ReadFile(argv[curArgIndex], argc - curArgIndex - 1);
|
||||
obj_Setup(argc - musl_optind);
|
||||
for (int i = musl_optind; i < argc; ++i) {
|
||||
obj_ReadFile(argv[i], argc - i - 1);
|
||||
}
|
||||
|
||||
// apply the linker script's modifications,
|
||||
if (linkerScriptName) {
|
||||
verbosePrint("Reading linker script...\n");
|
||||
verbosePrint(VERB_NOTICE, "Reading linker script...\n");
|
||||
|
||||
if (lexer_Init(linkerScriptName)) {
|
||||
yy::parser parser;
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
#include "helpers.hpp"
|
||||
#include "linkdefs.hpp"
|
||||
#include "platform.hpp"
|
||||
#include "verbosity.hpp"
|
||||
#include "version.hpp"
|
||||
|
||||
#include "link/assign.hpp"
|
||||
@@ -480,7 +481,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
|
||||
fatal("%s: Not a RGBDS object file", fileName);
|
||||
}
|
||||
|
||||
verbosePrint("Reading object file %s\n", fileName);
|
||||
verbosePrint(VERB_NOTICE, "Reading object file %s\n", fileName);
|
||||
|
||||
uint32_t revNum;
|
||||
tryReadLong(revNum, file, "%s: Cannot read revision number: %s", fileName);
|
||||
@@ -506,7 +507,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
|
||||
uint32_t nbNodes;
|
||||
tryReadLong(nbNodes, file, "%s: Cannot read number of nodes: %s", fileName);
|
||||
nodes[fileID].resize(nbNodes);
|
||||
verbosePrint("Reading %u nodes...\n", nbNodes);
|
||||
verbosePrint(VERB_INFO, "Reading %u nodes...\n", nbNodes);
|
||||
for (uint32_t i = nbNodes; i--;) {
|
||||
readFileStackNode(file, nodes[fileID], i, fileName);
|
||||
}
|
||||
@@ -515,7 +516,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
|
||||
std::vector<Symbol> &fileSymbols = symbolLists.emplace_front(nbSymbols);
|
||||
std::vector<uint32_t> nbSymPerSect(nbSections, 0);
|
||||
|
||||
verbosePrint("Reading %" PRIu32 " symbols...\n", nbSymbols);
|
||||
verbosePrint(VERB_INFO, "Reading %" PRIu32 " symbols...\n", nbSymbols);
|
||||
for (uint32_t i = 0; i < nbSymbols; ++i) {
|
||||
// Read symbol
|
||||
Symbol &symbol = fileSymbols[i];
|
||||
@@ -531,7 +532,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
|
||||
// This file's sections, stored in a table to link symbols to them
|
||||
std::vector<std::unique_ptr<Section>> fileSections(nbSections);
|
||||
|
||||
verbosePrint("Reading %" PRIu32 " sections...\n", nbSections);
|
||||
verbosePrint(VERB_INFO, "Reading %" PRIu32 " sections...\n", nbSections);
|
||||
for (uint32_t i = 0; i < nbSections; ++i) {
|
||||
// Read section
|
||||
fileSections[i] = std::make_unique<Section>();
|
||||
@@ -543,7 +544,7 @@ void obj_ReadFile(char const *fileName, unsigned int fileID) {
|
||||
|
||||
uint32_t nbAsserts;
|
||||
tryReadLong(nbAsserts, file, "%s: Cannot read number of assertions: %s", fileName);
|
||||
verbosePrint("Reading %" PRIu32 " assertions...\n", nbAsserts);
|
||||
verbosePrint(VERB_INFO, "Reading %" PRIu32 " assertions...\n", nbAsserts);
|
||||
for (uint32_t i = 0; i < nbAsserts; ++i) {
|
||||
Assertion &assertion = patch_AddAssertion();
|
||||
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "helpers.hpp" // assume, clz, ctz
|
||||
#include "linkdefs.hpp"
|
||||
#include "opmath.hpp"
|
||||
#include "verbosity.hpp"
|
||||
|
||||
#include "link/main.hpp"
|
||||
#include "link/section.hpp"
|
||||
@@ -462,7 +463,7 @@ Assertion &patch_AddAssertion() {
|
||||
}
|
||||
|
||||
void patch_CheckAssertions() {
|
||||
verbosePrint("Checking assertions...\n");
|
||||
verbosePrint(VERB_NOTICE, "Checking assertions...\n");
|
||||
|
||||
for (Assertion &assert : assertions) {
|
||||
int32_t value = computeRPNExpr(assert.patch, *assert.fileSymbols);
|
||||
@@ -505,7 +506,7 @@ void patch_CheckAssertions() {
|
||||
|
||||
// Applies all of a section's patches to a data section
|
||||
static void applyFilePatches(Section §ion, Section &dataSection) {
|
||||
verbosePrint("Patching section \"%s\"...\n", section.name.c_str());
|
||||
verbosePrint(VERB_INFO, "Patching section \"%s\"...\n", section.name.c_str());
|
||||
for (Patch &patch : section.patches) {
|
||||
int32_t value = computeRPNExpr(patch, *section.fileSymbols);
|
||||
uint16_t offset = patch.offset + section.offset;
|
||||
|
||||
Reference in New Issue
Block a user