Output the map file summary at the top of the file (#1203)

This commit is contained in:
Rangi
2023-11-05 09:43:58 -05:00
committed by GitHub
parent f8af569680
commit 143e76b7e3
2 changed files with 82 additions and 70 deletions

View File

@@ -679,7 +679,7 @@ int main(int argc, char *argv[]) {
fprintf(stderr, "rgbgfx %s\n", get_package_version_string()); fprintf(stderr, "rgbgfx %s\n", get_package_version_string());
if (options.verbosity >= Options::VERB_VVVVVV) { if (options.verbosity >= Options::VERB_VVVVVV) {
fputc('\n', stderr); putc('\n', stderr);
static std::array<uint16_t, 21> gfx{ static std::array<uint16_t, 21> gfx{
0x1FE, 0x3FF, 0x399, 0x399, 0x3FF, 0x3FF, 0x381, 0x3C3, 0x1FE, 0x078, 0x1FE, 0x1FE, 0x3FF, 0x399, 0x399, 0x3FF, 0x3FF, 0x381, 0x3C3, 0x1FE, 0x078, 0x1FE,
0x3FF, 0x3FF, 0x3FF, 0x37B, 0x37B, 0x0FC, 0x0CC, 0x1CE, 0x1CE, 0x1CE, 0x3FF, 0x3FF, 0x3FF, 0x37B, 0x37B, 0x0FC, 0x0CC, 0x1CE, 0x1CE, 0x1CE,
@@ -692,17 +692,17 @@ int main(int argc, char *argv[]) {
uint16_t row = gfx[i]; uint16_t row = gfx[i];
for (uint8_t _ = 0; _ < 10; ++_) { for (uint8_t _ = 0; _ < 10; ++_) {
unsigned char c = row & 1 ? '0' : ' '; unsigned char c = row & 1 ? '0' : ' ';
fputc(c, stderr); putc(c, stderr);
// Double the pixel horizontally, otherwise the aspect ratio looks wrong // Double the pixel horizontally, otherwise the aspect ratio looks wrong
fputc(c, stderr); putc(c, stderr);
row >>= 1; row >>= 1;
} }
if (i < textbox.size()) { if (i < textbox.size()) {
fputs(textbox[i], stderr); fputs(textbox[i], stderr);
} }
fputc('\n', stderr); putc('\n', stderr);
} }
fputc('\n', stderr); putc('\n', stderr);
} }
fputs("Options:\n", stderr); fputs("Options:\n", stderr);

View File

@@ -200,8 +200,7 @@ static void writeBank(struct SortedSection *bankSections, uint16_t baseOffset,
assert(section->offset == 0); assert(section->offset == 0);
// Output padding up to the next SECTION // Output padding up to the next SECTION
while (offset + baseOffset < section->org) { while (offset + baseOffset < section->org) {
putc(overlayFile ? getc(overlayFile) : padValue, putc(overlayFile ? getc(overlayFile) : padValue, outputFile);
outputFile);
offset++; offset++;
} }
@@ -220,9 +219,7 @@ static void writeBank(struct SortedSection *bankSections, uint16_t baseOffset,
if (!disablePadding) { if (!disablePadding) {
while (offset < size) { while (offset < size) {
putc(overlayFile ? getc(overlayFile) putc(overlayFile ? getc(overlayFile) : padValue, outputFile);
: padValue,
outputFile);
offset++; offset++;
} }
} }
@@ -292,7 +289,7 @@ static void printSymName(char const *name)
if (isLegalForSymName(c)) { if (isLegalForSymName(c)) {
// Output legal ASCII characters as-is // Output legal ASCII characters as-is
fputc(c, symFile); putc(c, symFile);
++ptr; ++ptr;
} else { } else {
// Output illegal characters using Unicode escapes // Output illegal characters using Unicode escapes
@@ -357,9 +354,6 @@ static int compareSymbols(void const *a, void const *b)
static void writeSymBank(struct SortedSections const *bankSections, static void writeSymBank(struct SortedSections const *bankSections,
enum SectionType type, uint32_t bank) enum SectionType type, uint32_t bank)
{ {
if (!symFile)
return;
#define forEachSortedSection(sect, ...) do { \ #define forEachSortedSection(sect, ...) do { \
for (struct SortedSection const *ssp = bankSections->zeroLenSections; ssp; ssp = ssp->next) { \ for (struct SortedSection const *ssp = bankSections->zeroLenSections; ssp; ssp = ssp->next) { \
for (struct Section const *sect = ssp->section; sect; sect = sect->nextu) \ for (struct Section const *sect = ssp->section; sect; sect = sect->nextu) \
@@ -410,7 +404,7 @@ static void writeSymBank(struct SortedSections const *bankSections,
fprintf(symFile, "%02" PRIx32 ":%04" PRIx16 " ", symBank, sym->addr); fprintf(symFile, "%02" PRIx32 ":%04" PRIx16 " ", symBank, sym->addr);
printSymName(sym->sym->name); printSymName(sym->sym->name);
fputc('\n', symFile); putc('\n', symFile);
} }
free(symList); free(symList);
@@ -429,22 +423,16 @@ static void writeEmptySpace(uint16_t begin, uint16_t end)
/* /*
* Write a bank's contents to the map file * Write a bank's contents to the map file
* @param bankSections The bank's sections
* @return The bank's used space
*/ */
static uint16_t writeMapBank(struct SortedSections const *sectList, static void writeMapBank(struct SortedSections const *sectList, enum SectionType type,
enum SectionType type, uint32_t bank) uint32_t bank)
{ {
if (!mapFile) fprintf(mapFile, "\n%s bank #%" PRIu32 ":\n", sectionTypeInfo[type].name,
return 0;
struct SortedSection const *section = sectList->sections;
struct SortedSection const *zeroLenSection = sectList->zeroLenSections;
fprintf(mapFile, "%s bank #%" PRIu32 ":\n", sectionTypeInfo[type].name,
bank + sectionTypeInfo[type].firstBank); bank + sectionTypeInfo[type].firstBank);
uint16_t used = 0; uint16_t used = 0;
struct SortedSection const *section = sectList->sections;
struct SortedSection const *zeroLenSection = sectList->zeroLenSections;
uint16_t prevEndAddr = sectionTypeInfo[type].startAddr; uint16_t prevEndAddr = sectionTypeInfo[type].startAddr;
while (section || zeroLenSection) { while (section || zeroLenSection) {
@@ -496,83 +484,109 @@ static uint16_t writeMapBank(struct SortedSections const *sectList,
*pickedSection = (*pickedSection)->next; *pickedSection = (*pickedSection)->next;
} }
if (used == 0) {
fputs("\tEMPTY\n", mapFile);
} else {
uint16_t bankEndAddr = sectionTypeInfo[type].startAddr + sectionTypeInfo[type].size; uint16_t bankEndAddr = sectionTypeInfo[type].startAddr + sectionTypeInfo[type].size;
if (used == 0) {
fputs("\tEMPTY\n\n", mapFile);
} else {
writeEmptySpace(prevEndAddr, bankEndAddr); writeEmptySpace(prevEndAddr, bankEndAddr);
uint16_t slack = sectionTypeInfo[type].size - used; uint16_t slack = sectionTypeInfo[type].size - used;
fprintf(mapFile, "\tTOTAL EMPTY: $%04" PRIx16 " byte%s\n\n", slack, fprintf(mapFile, "\tTOTAL EMPTY: $%04" PRIx16 " byte%s\n", slack,
slack == 1 ? "" : "s"); slack == 1 ? "" : "s");
} }
return used;
} }
/* /*
* Write the total used and free space by section type to the map file * Write the total used and free space by section type to the map file
* @param usedMap The total used space by section type
*/ */
static void writeMapSummary(uint32_t usedMap[MIN_NB_ELMS(SECTTYPE_INVALID)]) static void writeMapSummary(void)
{ {
if (!mapFile)
return;
fputs("SUMMARY:\n", mapFile); fputs("SUMMARY:\n", mapFile);
for (uint8_t i = 0; i < SECTTYPE_INVALID; i++) { for (uint8_t i = 0; i < SECTTYPE_INVALID; i++) {
enum SectionType type = typeMap[i]; enum SectionType type = typeMap[i];
uint32_t nbBanks = sections[type].nbBanks;
// Do not output used space for VRAM or OAM // Do not output used space for VRAM or OAM
if (type == SECTTYPE_VRAM || type == SECTTYPE_OAM) if (type == SECTTYPE_VRAM || type == SECTTYPE_OAM)
continue; continue;
// Do not output unused section types // Do not output unused section types
if (sections[type].nbBanks == 0) if (nbBanks == 0)
continue; continue;
uint32_t usedTotal = 0;
for (uint32_t bank = 0; bank < nbBanks; bank++) {
uint16_t used = 0;
struct SortedSections const *sectList = &sections[type].banks[bank];
struct SortedSection const *section = sectList->sections;
struct SortedSection const *zeroLenSection = sectList->zeroLenSections;
while (section || zeroLenSection) {
struct SortedSection const **pickedSection =
nextSection(&section, &zeroLenSection);
used += (*pickedSection)->section->size;
*pickedSection = (*pickedSection)->next;
}
usedTotal += used;
}
fprintf(mapFile, "\t%s: %" PRId32 " byte%s used / %" PRId32 " free", fprintf(mapFile, "\t%s: %" PRId32 " byte%s used / %" PRId32 " free",
sectionTypeInfo[type].name, usedMap[type], usedMap[type] == 1 ? "" : "s", sectionTypeInfo[type].name, usedTotal, usedTotal == 1 ? "" : "s",
sections[type].nbBanks * sectionTypeInfo[type].size - usedMap[type]); nbBanks * sectionTypeInfo[type].size - usedTotal);
if (sectionTypeInfo[type].firstBank != sectionTypeInfo[type].lastBank || if (sectionTypeInfo[type].firstBank != sectionTypeInfo[type].lastBank
sections[type].nbBanks > 1) || nbBanks > 1)
fprintf(mapFile, " in %d bank%s", sections[type].nbBanks, fprintf(mapFile, " in %d bank%s", nbBanks, nbBanks == 1 ? "" : "s");
sections[type].nbBanks == 1 ? "" : "s"); putc('\n', mapFile);
fputc('\n', mapFile);
} }
} }
// Writes the sym and/or map files, if applicable. // Writes the sym file, if applicable.
static void writeSymAndMap(void) static void writeSym(void)
{ {
if (!symFileName && !mapFileName) if (!symFileName)
return; return;
uint32_t usedMap[SECTTYPE_INVALID] = {0};
symFile = openFile(symFileName, "w"); symFile = openFile(symFileName, "w");
mapFile = openFile(mapFileName, "w"); if (!symFile)
err("Failed to open sym file \"%s\"", symFileName);
if (symFileName)
fputs("; File generated by rgblink\n", symFile); fputs("; File generated by rgblink\n", symFile);
for (uint8_t i = 0; i < SECTTYPE_INVALID; i++) { for (uint8_t i = 0; i < SECTTYPE_INVALID; i++) {
enum SectionType type = typeMap[i]; enum SectionType type = typeMap[i];
for (uint32_t bank = 0; bank < sections[type].nbBanks; bank++) { for (uint32_t bank = 0; bank < sections[type].nbBanks; bank++)
struct SortedSections const *sect = &sections[type].banks[bank]; writeSymBank(&sections[type].banks[bank], type, bank);
writeSymBank(sect, type, bank);
usedMap[type] += writeMapBank(sect, type, bank);
} }
}
writeMapSummary(usedMap);
closeFile(symFile); closeFile(symFile);
}
// Writes the map file, if applicable.
static void writeMap(void)
{
if (!mapFileName)
return;
mapFile = openFile(mapFileName, "w");
if (!mapFile)
err("Failed to open map file \"%s\"", mapFileName);
writeMapSummary();
for (uint8_t i = 0; i < SECTTYPE_INVALID; i++) {
enum SectionType type = typeMap[i];
for (uint32_t bank = 0; bank < sections[type].nbBanks; bank++)
writeMapBank(&sections[type].banks[bank], type, bank);
}
closeFile(mapFile); closeFile(mapFile);
} }
@@ -589,23 +603,21 @@ static void cleanupSections(struct SortedSection *section)
static void cleanup(void) static void cleanup(void)
{ {
for (enum SectionType type = 0; type < SECTTYPE_INVALID; type++) { for (enum SectionType type = 0; type < SECTTYPE_INVALID; type++) {
if (sections[type].nbBanks > 0) {
for (uint32_t i = 0; i < sections[type].nbBanks; i++) { for (uint32_t i = 0; i < sections[type].nbBanks; i++) {
struct SortedSections *bank = struct SortedSections *bank = &sections[type].banks[i];
&sections[type].banks[i];
cleanupSections(bank->sections); cleanupSections(bank->sections);
cleanupSections(bank->zeroLenSections); cleanupSections(bank->zeroLenSections);
} }
free(sections[type].banks); free(sections[type].banks);
} }
}
} }
void out_WriteFiles(void) void out_WriteFiles(void)
{ {
writeROM(); writeROM();
writeSymAndMap(); writeSym();
writeMap();
cleanup(); cleanup();
} }