diff --git a/include/link/output.h b/include/link/output.h index 7c43d2c3..0cf531c6 100644 --- a/include/link/output.h +++ b/include/link/output.h @@ -14,8 +14,15 @@ #include "link/section.h" +/** + * Registers a section for output. + * @param section The section to add + */ void out_AddSection(struct Section const *section); +/** + * Writes all output (bin, sym, map) files. + */ void out_WriteFiles(void); #endif /* RGBDS_LINK_OUTPUT_H */ diff --git a/src/link/assign.c b/src/link/assign.c index 5fa70b35..4780e120 100644 --- a/src/link/assign.c +++ b/src/link/assign.c @@ -104,6 +104,15 @@ static inline void assignSection(struct Section *section, out_AddSection(section); } +/** + * Checks whether a given location is suitable for placing a given section + * This checks not only that the location has enough room for the section, but + * also that the constraints (alignment...) are respected. + * @param section The section to be placed + * @param freeSpace The candidate free space to place the section into + * @param location The location to attempt placing the section at + * @return True if the location is suitable, false otherwise. + */ static bool isLocationSuitable(struct Section const *section, struct FreeSpace const *freeSpace, struct MemoryLocation const *location) @@ -118,6 +127,13 @@ static bool isLocationSuitable(struct Section const *section, <= freeSpace->address + freeSpace->size; } +/** + * Finds a suitable location to place a section at. + * @param section The section to be placed + * @param location A pointer to a location struct that will be filled + * @return A pointer to the free space encompassing the location, or NULL if + * none was found + */ static struct FreeSpace *getPlacement(struct Section const *section, struct MemoryLocation *location) { @@ -177,9 +193,16 @@ static struct FreeSpace *getPlacement(struct Section const *section, location->bank++; if (location->bank > bankranges[section->type][1]) return NULL; +#undef BANK_INDEX } } +/** + * Places a section in a suitable location, or error out if it fails to. + * @warning Due to the implemented algorithm, this should be called with + * sections of decreasing size. + * @param section The section to place + */ static void placeSection(struct Section *section) { struct MemoryLocation location; @@ -293,6 +316,12 @@ struct UnassignedSection { static struct UnassignedSection *unassignedSections[1 << 3] = {0}; static struct UnassignedSection *sections; +/** + * Categorize a section depending on how constrained it is + * This is so the most-constrained sections are placed first + * @param section The section to categorize + * @param arg Callback arg, unused + */ static void categorizeSection(struct Section *section, void *arg) { (void)arg; diff --git a/src/link/object.c b/src/link/object.c index 28c7633e..3585f64e 100644 --- a/src/link/object.c +++ b/src/link/object.c @@ -145,6 +145,12 @@ static char *readstr(FILE *file) /***** Functions to parse object files *****/ +/** + * Reads a RGB6 symbol from a file. + * @param file The file to read from + * @param symbol The struct to fill + * @param fileName The filename to report in errors + */ static void readSymbol(FILE *file, struct Symbol *symbol, char const *fileName) { tryReadstr(symbol->name, file, "%s: Cannot read symbol name: %s", @@ -171,6 +177,13 @@ static void readSymbol(FILE *file, struct Symbol *symbol, char const *fileName) } } +/** + * Reads a RGB6 patch from a file. + * @param file The file to read from + * @param patch The struct to fill + * @param fileName The filename to report in errors + * @param i The number of the patch to report in errors + */ static void readPatch(FILE *file, struct Patch *patch, char const *fileName, char const *sectName, uint32_t i) { @@ -201,6 +214,12 @@ static void readPatch(FILE *file, struct Patch *patch, patch->rpnExpression = rpnExpression; } +/** + * Reads a RGB6 section from a file. + * @param file The file to read from + * @param section The struct to fill + * @param fileName The filename to report in errors + */ static void readSection(FILE *file, struct Section *section, char const *fileName) { @@ -266,6 +285,11 @@ static void readSection(FILE *file, struct Section *section, } } +/** + * Links a symbol to a section, keeping the section's symbol list sorted. + * @param symbol The symbol to link + * @param section The section to link + */ static void linkSymToSect(struct Symbol const *symbol, struct Section *section) { uint32_t a = 0, b = section->nbSymbols; @@ -290,6 +314,11 @@ static void linkSymToSect(struct Symbol const *symbol, struct Section *section) section->nbSymbols++; } +/** + * Reads a RGB6 object file. + * @param file The file to read from + * @param fileName The filename to report in errors + */ static void readRGB6File(FILE *file, char const *fileName) { uint32_t nbSymbols; @@ -378,6 +407,10 @@ static void readRGB6File(FILE *file, char const *fileName) } } +/** + * Reads an object file of any supported format + * @param fileName The filename to report for errors + */ void obj_ReadFile(char const *fileName) { FILE *file = strcmp("-", fileName) ? fopen(fileName, "rb") : stdin; diff --git a/src/link/output.c b/src/link/output.c index 81605c2b..6f99e66e 100644 --- a/src/link/output.c +++ b/src/link/output.c @@ -73,6 +73,9 @@ void out_AddSection(struct Section const *section) *ptr = newSection; } +/** + * Performs sanity checks on the overlay file. + */ static void checkOverlay(void) { if (!overlayFile) @@ -88,6 +91,9 @@ static void checkOverlay(void) if (overlaySize % 0x4000) errx(1, "Overlay file must have a size multiple of 0x4000"); + /* Reset back to beginning */ + fseek(overlayFile, 0, SEEK_SET); + uint32_t nbOverlayBanks = overlaySize / 0x4000 - 1; if (nbOverlayBanks < 1) @@ -104,6 +110,12 @@ static void checkOverlay(void) } } +/** + * Write a ROM bank's sections to the output file. + * @param bankSections The bank's sections, ordered by increasing address + * @param baseOffset The address of the bank's first byte in GB address space + * @param size The size of the bank + */ static void writeBank(struct SortedSection *bankSections, uint16_t baseOffset, uint16_t size) { @@ -141,6 +153,9 @@ static void writeBank(struct SortedSection *bankSections, uint16_t baseOffset, } } +/** + * Writes a ROM file to the output. + */ static void writeROM(void) { checkOverlay(); @@ -164,6 +179,12 @@ static void writeROM(void) } } +/** + * Get the lowest section by address out of the two + * @param s1 One choice + * @param s2 The other + * @return The lowest section of the two, or the non-NULL one if applicable + */ static struct SortedSection const **nextSection(struct SortedSection const **s1, struct SortedSection const **s2) { @@ -175,6 +196,10 @@ static struct SortedSection const **nextSection(struct SortedSection const **s1, return (*s1)->section->org < (*s2)->section->org ? s1 : s2; } +/** + * Write a bank's contents to the sym file + * @param bankSections The bank's sections + */ static void writeSymBank(struct SortedSections const *bankSections) { if (!symFile) @@ -236,6 +261,10 @@ static void writeSymBank(struct SortedSections const *bankSections) #undef sect } +/** + * Write a bank's contents to the map file + * @param bankSections The bank's sections + */ static void writeMapBank(struct SortedSections const *sectList, enum SectionType type, uint32_t bank) { @@ -276,6 +305,9 @@ static void writeMapBank(struct SortedSections const *sectList, slack == 1 ? "" : "s"); } +/** + * Writes the sym and/or map files, if applicable. + */ static void writeSymAndMap(void) { if (!symFile && !mapFile) diff --git a/src/link/patch.c b/src/link/patch.c index bc86fb06..255a7f7a 100644 --- a/src/link/patch.c +++ b/src/link/patch.c @@ -69,6 +69,12 @@ static uint8_t getRPNByte(uint8_t const **expression, int32_t *size, return *(*expression)++; } +/** + * Compute a patch's value from its RPN string. + * @param patch The patch to compute the value of + * @param section The section the patch is contained in + * @return The patch's value + */ static int32_t computeRPNExpr(struct Patch const *patch, struct Section const *section) { @@ -272,6 +278,11 @@ static int32_t computeRPNExpr(struct Patch const *patch, return popRPN(); } +/** + * Applies all of a section's patches + * @param section The section to patch + * @param arg Ignored callback arg + */ static void applyPatches(struct Section *section, void *arg) { (void)arg; diff --git a/src/link/script.c b/src/link/script.c index 0f499370..1f5880ad 100644 --- a/src/link/script.c +++ b/src/link/script.c @@ -21,6 +21,13 @@ static inline bool isNewline(int c) return c == '\r' || c == '\n'; } +/** + * Try parsing a number, in base 16 if it begins with a dollar, + * in base 10 otherwise + * @param str The number to parse + * @param number A pointer where the number will be written to + * @return True if parsing was successful, false otherwise + */ static bool tryParseNumber(char const *str, uint32_t *number) { static char const digits[] = {