Use std::deque for sorted sections

This commit is contained in:
Rangi42
2024-02-21 14:50:25 -05:00
committed by Sylvie
parent d53bba97e8
commit b74b40abd2

View File

@@ -1,6 +1,7 @@
/* SPDX-License-Identifier: MIT */ /* SPDX-License-Identifier: MIT */
#include <assert.h> #include <assert.h>
#include <deque>
#include <inttypes.h> #include <inttypes.h>
#include <stdint.h> #include <stdint.h>
#include <stdio.h> #include <stdio.h>
@@ -26,11 +27,6 @@ FILE *overlayFile;
FILE *symFile; FILE *symFile;
FILE *mapFile; FILE *mapFile;
struct SortedSection {
struct Section const *section;
struct SortedSection *next;
};
struct SortedSymbol { struct SortedSymbol {
struct Symbol const *sym; struct Symbol const *sym;
uint32_t idx; uint32_t idx;
@@ -38,14 +34,11 @@ struct SortedSymbol {
}; };
struct SortedSections { struct SortedSections {
struct SortedSection *sections; std::deque<struct Section const *> sections;
struct SortedSection *zeroLenSections; std::deque<struct Section const *> zeroLenSections;
}; };
static struct { static std::deque<struct SortedSections> sections[SECTTYPE_INVALID];
uint32_t nbBanks; // Size of the array below (which may be NULL if this is 0)
struct SortedSections *banks;
} sections[SECTTYPE_INVALID];
// Defines the order in which types are output to the sym and map files // Defines the order in which types are output to the sym and map files
static enum SectionType typeMap[SECTTYPE_INVALID] = { static enum SectionType typeMap[SECTTYPE_INVALID] = {
@@ -80,46 +73,27 @@ void out_AddSection(struct Section const *section)
section->name, section->bank, section->name, section->bank,
maxNbBanks[section->type] - 1); maxNbBanks[section->type] - 1);
if (minNbBanks > sections[section->type].nbBanks) { for (uint32_t i = sections[section->type].size(); i < minNbBanks; i++)
sections[section->type].banks = sections[section->type].emplace_back();
(struct SortedSections *)realloc(sections[section->type].banks,
sizeof(*sections[0].banks) * minNbBanks);
for (uint32_t i = sections[section->type].nbBanks; i < minNbBanks; i++) {
sections[section->type].banks[i].sections = NULL;
sections[section->type].banks[i].zeroLenSections = NULL;
}
sections[section->type].nbBanks = minNbBanks;
}
if (!sections[section->type].banks)
err("Failed to realloc banks");
struct SortedSection *newSection = (struct SortedSection *)malloc(sizeof(*newSection)); std::deque<struct Section const *> *ptr = section->size
struct SortedSection **ptr = section->size ? &sections[section->type][targetBank].sections
? &sections[section->type].banks[targetBank].sections : &sections[section->type][targetBank].zeroLenSections;
: &sections[section->type].banks[targetBank].zeroLenSections; auto pos = ptr->begin();
if (!newSection) while (pos != ptr->end() && (*pos)->org < section->org)
err("Failed to add new section \"%s\"", section->name); pos++;
newSection->section = section;
while (*ptr && (*ptr)->section->org < section->org) ptr->insert(pos, section);
ptr = &(*ptr)->next;
newSection->next = *ptr;
*ptr = newSection;
} }
struct Section const *out_OverlappingSection(struct Section const *section) struct Section const *out_OverlappingSection(struct Section const *section)
{ {
struct SortedSections *banks = sections[section->type].banks; uint32_t bank = section->bank - sectionTypeInfo[section->type].firstBank;
struct SortedSection *ptr =
banks[section->bank - sectionTypeInfo[section->type].firstBank].sections;
while (ptr) { for (struct Section const *ptr : sections[section->type][bank].sections) {
if (ptr->section->org < section->org + section->size if (ptr->org < section->org + section->size && section->org < ptr->org + ptr->size)
&& section->org < ptr->section->org + ptr->section->size) return ptr;
return ptr->section;
ptr = ptr->next;
} }
return NULL; return NULL;
} }
@@ -158,8 +132,8 @@ static uint32_t checkOverlaySize(void)
} }
/* /*
* Expand sections[SECTTYPE_ROMX].banks to cover all the overlay banks. * Expand `sections[SECTTYPE_ROMX]` to cover all the overlay banks.
* This ensures that writeROM will output each bank, even if some are not * This ensures that `writeROM` will output each bank, even if some are not
* covered by any sections. * covered by any sections.
* @param nbOverlayBanks The number of banks in the overlay file * @param nbOverlayBanks The number of banks in the overlay file
*/ */
@@ -168,21 +142,13 @@ static void coverOverlayBanks(uint32_t nbOverlayBanks)
// 2 if is32kMode, 1 otherwise // 2 if is32kMode, 1 otherwise
uint32_t nbRom0Banks = sectionTypeInfo[SECTTYPE_ROM0].size / BANK_SIZE; uint32_t nbRom0Banks = sectionTypeInfo[SECTTYPE_ROM0].size / BANK_SIZE;
// Discount ROM0 banks to avoid outputting too much // Discount ROM0 banks to avoid outputting too much
uint32_t nbUncoveredBanks = nbOverlayBanks - nbRom0Banks > sections[SECTTYPE_ROMX].nbBanks uint32_t nbUncoveredBanks = nbOverlayBanks - nbRom0Banks > sections[SECTTYPE_ROMX].size()
? nbOverlayBanks - nbRom0Banks ? nbOverlayBanks - nbRom0Banks
: 0; : 0;
if (nbUncoveredBanks > sections[SECTTYPE_ROMX].nbBanks) { if (nbUncoveredBanks > sections[SECTTYPE_ROMX].size()) {
sections[SECTTYPE_ROMX].banks = for (uint32_t i = sections[SECTTYPE_ROMX].size(); i < nbUncoveredBanks; i++)
(struct SortedSections *)realloc(sections[SECTTYPE_ROMX].banks, sections[SECTTYPE_ROMX].emplace_back();
sizeof(*sections[SECTTYPE_ROMX].banks) * nbUncoveredBanks);
if (!sections[SECTTYPE_ROMX].banks)
err("Failed to realloc banks for overlay");
for (uint32_t i = sections[SECTTYPE_ROMX].nbBanks; i < nbUncoveredBanks; i++) {
sections[SECTTYPE_ROMX].banks[i].sections = NULL;
sections[SECTTYPE_ROMX].banks[i].zeroLenSections = NULL;
}
sections[SECTTYPE_ROMX].nbBanks = nbUncoveredBanks;
} }
} }
@@ -192,14 +158,13 @@ static void coverOverlayBanks(uint32_t nbOverlayBanks)
* @param baseOffset The address of the bank's first byte in GB address space * @param baseOffset The address of the bank's first byte in GB address space
* @param size The size of the bank * @param size The size of the bank
*/ */
static void writeBank(struct SortedSection *bankSections, uint16_t baseOffset, static void writeBank(std::deque<struct Section const *> *bankSections, uint16_t baseOffset,
uint16_t size) uint16_t size)
{ {
uint16_t offset = 0; uint16_t offset = 0;
while (bankSections) { if (bankSections) {
struct Section const *section = bankSections->section; for (struct Section const *section : *bankSections) {
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) {
@@ -208,16 +173,14 @@ static void writeBank(struct SortedSection *bankSections, uint16_t baseOffset,
} }
// Output the section itself // Output the section itself
fwrite(section->data, sizeof(*section->data), section->size, fwrite(section->data, sizeof(*section->data), section->size, outputFile);
outputFile);
if (overlayFile) { if (overlayFile) {
// Skip bytes even with pipes // Skip bytes even with pipes
for (uint16_t i = 0; i < section->size; i++) for (uint16_t i = 0; i < section->size; i++)
getc(overlayFile); getc(overlayFile);
} }
offset += section->size; offset += section->size;
}
bankSections = bankSections->next;
} }
if (!disablePadding) { if (!disablePadding) {
@@ -259,12 +222,11 @@ static void writeROM(void)
coverOverlayBanks(nbOverlayBanks); coverOverlayBanks(nbOverlayBanks);
if (outputFile) { if (outputFile) {
writeBank(sections[SECTTYPE_ROM0].banks ? sections[SECTTYPE_ROM0].banks[0].sections writeBank(!sections[SECTTYPE_ROM0].empty() ? &sections[SECTTYPE_ROM0][0].sections : NULL,
: NULL,
sectionTypeInfo[SECTTYPE_ROM0].startAddr, sectionTypeInfo[SECTTYPE_ROM0].size); sectionTypeInfo[SECTTYPE_ROM0].startAddr, sectionTypeInfo[SECTTYPE_ROM0].size);
for (uint32_t i = 0 ; i < sections[SECTTYPE_ROMX].nbBanks; i++) for (uint32_t i = 0 ; i < sections[SECTTYPE_ROMX].size(); i++)
writeBank(sections[SECTTYPE_ROMX].banks[i].sections, writeBank(&sections[SECTTYPE_ROMX][i].sections,
sectionTypeInfo[SECTTYPE_ROMX].startAddr, sectionTypeInfo[SECTTYPE_ROMX].size); sectionTypeInfo[SECTTYPE_ROMX].startAddr, sectionTypeInfo[SECTTYPE_ROMX].size);
} }
@@ -274,23 +236,6 @@ static void writeROM(void)
fclose(overlayFile); fclose(overlayFile);
} }
/*
* 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)
{
if (!*s1)
return s2;
if (!*s2)
return s1;
return (*s1)->section->org < (*s2)->section->org ? s1 : s2;
}
// Checks whether this character is legal as the first character of a symbol's name in a sym file // Checks whether this character is legal as the first character of a symbol's name in a sym file
static bool canStartSymName(char c) static bool canStartSymName(char c)
{ {
@@ -375,16 +320,16 @@ static int compareSymbols(void const *a, void const *b)
* Write a bank's contents to the sym file * Write a bank's contents to the sym file
* @param bankSections The bank's sections * @param bankSections The bank's sections
*/ */
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)
{ {
#define forEachSortedSection(sect, ...) do { \ #define forEachSortedSection(sect, ...) do { \
for (struct SortedSection const *ssp = bankSections->zeroLenSections; ssp; ssp = ssp->next) { \ for (auto it = bankSections.zeroLenSections.begin(); it != bankSections.zeroLenSections.end(); it++) { \
for (struct Section const *sect = ssp->section; sect; sect = sect->nextu) \ for (struct Section const *sect = *it; sect; sect = sect->nextu) \
__VA_ARGS__ \ __VA_ARGS__ \
} \ } \
for (struct SortedSection const *ssp = bankSections->sections; ssp; ssp = ssp->next) { \ for (auto it = bankSections.sections.begin(); it != bankSections.sections.end(); it++) { \
for (struct Section const *sect = ssp->section; sect; sect = sect->nextu) \ for (struct Section const *sect = *it; sect; sect = sect->nextu) \
__VA_ARGS__ \ __VA_ARGS__ \
} \ } \
} while (0) } while (0)
@@ -432,7 +377,6 @@ static void writeSymBank(struct SortedSections const *bankSections,
} }
free(symList); free(symList);
} }
static void writeEmptySpace(uint16_t begin, uint16_t end) static void writeEmptySpace(uint16_t begin, uint16_t end)
@@ -448,21 +392,23 @@ 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
*/ */
static void writeMapBank(struct SortedSections const *sectList, enum SectionType type, static void writeMapBank(struct SortedSections const &sectList, enum SectionType type,
uint32_t bank) uint32_t bank)
{ {
fprintf(mapFile, "\n%s bank #%" PRIu32 ":\n", sectionTypeInfo[type].name.c_str(), fprintf(mapFile, "\n%s bank #%" PRIu32 ":\n", sectionTypeInfo[type].name.c_str(),
bank + sectionTypeInfo[type].firstBank); bank + sectionTypeInfo[type].firstBank);
uint16_t used = 0; uint16_t used = 0;
struct SortedSection const *section = sectList->sections; auto section = sectList.sections.begin();
struct SortedSection const *zeroLenSection = sectList->zeroLenSections; auto zeroLenSection = sectList.zeroLenSections.begin();
uint16_t prevEndAddr = sectionTypeInfo[type].startAddr; uint16_t prevEndAddr = sectionTypeInfo[type].startAddr;
while (section || zeroLenSection) { while (section != sectList.sections.end() || zeroLenSection != sectList.zeroLenSections.end()) {
struct SortedSection const **pickedSection = // Pick the lowest section by address out of the two
nextSection(&section, &zeroLenSection); auto &pickedSection = section == sectList.sections.end() ? zeroLenSection
struct Section const *sect = (*pickedSection)->section; : zeroLenSection == sectList.zeroLenSections.end() ? section
: (*section)->org < (*zeroLenSection)->org ? section : zeroLenSection;
struct Section const *sect = *pickedSection;
used += sect->size; used += sect->size;
assert(sect->offset == 0); assert(sect->offset == 0);
@@ -505,7 +451,7 @@ static void writeMapBank(struct SortedSections const *sectList, enum SectionType
} }
} }
*pickedSection = (*pickedSection)->next; pickedSection++;
} }
if (used == 0) { if (used == 0) {
@@ -531,7 +477,7 @@ static void writeMapSummary(void)
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; uint32_t nbBanks = sections[type].size();
// 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)
@@ -545,16 +491,20 @@ static void writeMapSummary(void)
for (uint32_t bank = 0; bank < nbBanks; bank++) { for (uint32_t bank = 0; bank < nbBanks; bank++) {
uint16_t used = 0; uint16_t used = 0;
struct SortedSections const *sectList = &sections[type].banks[bank]; auto &sectList = sections[type][bank];
struct SortedSection const *section = sectList->sections; auto section = sectList.sections.begin();
struct SortedSection const *zeroLenSection = sectList->zeroLenSections; auto zeroLenSection = sectList.zeroLenSections.begin();
while (section || zeroLenSection) { while (section != sectList.sections.end()
struct SortedSection const **pickedSection = || zeroLenSection != sectList.zeroLenSections.end()) {
nextSection(&section, &zeroLenSection); // Pick the lowest section by address out of the two
auto &pickedSection = section == sectList.sections.end() ? zeroLenSection
: zeroLenSection == sectList.zeroLenSections.end() ? section
: (*section)->org < (*zeroLenSection)->org ? section
: zeroLenSection;
used += (*pickedSection)->section->size; used += (*pickedSection)->size;
*pickedSection = (*pickedSection)->next; pickedSection++;
} }
usedTotal += used; usedTotal += used;
@@ -590,8 +540,8 @@ static void writeSym(void)
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].size(); bank++)
writeSymBank(&sections[type].banks[bank], type, bank); writeSymBank(sections[type][bank], type, bank);
} }
fclose(symFile); fclose(symFile);
@@ -617,41 +567,16 @@ static void writeMap(void)
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].size(); bank++)
writeMapBank(&sections[type].banks[bank], type, bank); writeMapBank(sections[type][bank], type, bank);
} }
fclose(mapFile); fclose(mapFile);
} }
static void cleanupSections(struct SortedSection *section)
{
while (section) {
struct SortedSection *next = section->next;
free(section);
section = next;
}
}
static void cleanup(void)
{
for (enum SectionType type : EnumSeq(SECTTYPE_INVALID)) {
for (uint32_t i = 0; i < sections[type].nbBanks; i++) {
struct SortedSections *bank = &sections[type].banks[i];
cleanupSections(bank->sections);
cleanupSections(bank->zeroLenSections);
}
free(sections[type].banks);
}
}
void out_WriteFiles(void) void out_WriteFiles(void)
{ {
writeROM(); writeROM();
writeSym(); writeSym();
writeMap(); writeMap();
cleanup();
} }