mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Output the map file summary at the top of the file (#1203)
This commit is contained in:
@@ -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);
|
||||||
|
|||||||
@@ -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 = §ions[type].banks[bank];
|
||||||
|
struct SortedSection const *section = sectList->sections;
|
||||||
|
struct SortedSection const *zeroLenSection = sectList->zeroLenSections;
|
||||||
|
|
||||||
|
while (section || zeroLenSection) {
|
||||||
|
struct SortedSection const **pickedSection =
|
||||||
|
nextSection(§ion, &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 = §ions[type].banks[bank];
|
writeSymBank(§ions[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(§ions[type].banks[bank], type, bank);
|
||||||
|
}
|
||||||
|
|
||||||
closeFile(mapFile);
|
closeFile(mapFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -589,10 +603,8 @@ 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 = §ions[type].banks[i];
|
||||||
§ions[type].banks[i];
|
|
||||||
|
|
||||||
cleanupSections(bank->sections);
|
cleanupSections(bank->sections);
|
||||||
cleanupSections(bank->zeroLenSections);
|
cleanupSections(bank->zeroLenSections);
|
||||||
@@ -600,12 +612,12 @@ static void cleanup(void)
|
|||||||
free(sections[type].banks);
|
free(sections[type].banks);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
void out_WriteFiles(void)
|
void out_WriteFiles(void)
|
||||||
{
|
{
|
||||||
writeROM();
|
writeROM();
|
||||||
writeSymAndMap();
|
writeSym();
|
||||||
|
writeMap();
|
||||||
|
|
||||||
cleanup();
|
cleanup();
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user