diff --git a/include/linkdefs.h b/include/linkdefs.h index bd9cb99b..8cf3c8b9 100644 --- a/include/linkdefs.h +++ b/include/linkdefs.h @@ -79,13 +79,14 @@ enum SectionType { SECTTYPE_INVALID }; -enum SectionModifier { - SECTION_NORMAL, - SECTION_UNION, - SECTION_FRAGMENT -}; - -extern char const * const sectionModNames[]; +// Nont-`const` members may be patched in RGBLINK depending on CLI flags +extern struct SectionTypeInfo { + char const *const name; + uint16_t const startAddr; + uint16_t size; + uint32_t const firstBank; + uint32_t lastBank; +} sectionTypeInfo[SECTTYPE_INVALID]; /** * Tells whether a section has data in its object file definition, @@ -99,6 +100,32 @@ static inline bool sect_HasData(enum SectionType type) return type == SECTTYPE_ROM0 || type == SECTTYPE_ROMX; } +/** + * Computes a memory region's end address (last byte), eg. 0x7FFF + * @return The address of the last byte in that memory region + */ +static inline uint16_t endaddr(enum SectionType type) +{ + return sectionTypeInfo[type].startAddr + sectionTypeInfo[type].size - 1; +} + +/** + * Computes a memory region's number of banks + * @return The number of banks, 1 for regions without banking + */ +static inline uint32_t nbbanks(enum SectionType type) +{ + return sectionTypeInfo[type].lastBank - sectionTypeInfo[type].firstBank + 1; +} + +enum SectionModifier { + SECTION_NORMAL, + SECTION_UNION, + SECTION_FRAGMENT +}; + +extern char const * const sectionModNames[]; + enum ExportLevel { SYMTYPE_LOCAL, SYMTYPE_IMPORT, @@ -114,45 +141,4 @@ enum PatchType { PATCHTYPE_INVALID }; -#define BANK_MIN_ROM0 0 -#define BANK_MAX_ROM0 0 -#define BANK_MIN_ROMX 1 -#define BANK_MAX_ROMX 511 -#define BANK_MIN_VRAM 0 -#define BANK_MAX_VRAM 1 -#define BANK_MIN_SRAM 0 -#define BANK_MAX_SRAM 15 -#define BANK_MIN_WRAM0 0 -#define BANK_MAX_WRAM0 0 -#define BANK_MIN_WRAMX 1 -#define BANK_MAX_WRAMX 7 -#define BANK_MIN_OAM 0 -#define BANK_MAX_OAM 0 -#define BANK_MIN_HRAM 0 -#define BANK_MAX_HRAM 0 - -extern uint16_t startaddr[]; -extern uint16_t maxsize[]; -extern uint32_t bankranges[][2]; - -/** - * Computes a memory region's end address (last byte), eg. 0x7FFF - * @return The address of the last byte in that memory region - */ -static inline uint16_t endaddr(enum SectionType type) -{ - return startaddr[type] + maxsize[type] - 1; -} - -/** - * Computes a memory region's number of banks - * @return The number of banks, 1 for regions without banking - */ -static inline uint32_t nbbanks(enum SectionType type) -{ - return bankranges[type][1] - bankranges[type][0] + 1; -} - -extern char const * const typeNames[SECTTYPE_INVALID]; - #endif /* RGBDS_LINKDEFS_H */ diff --git a/src/asm/section.c b/src/asm/section.c index 1e69ee5c..84c6391a 100644 --- a/src/asm/section.c +++ b/src/asm/section.c @@ -16,6 +16,7 @@ #include "asm/warning.h" #include "error.h" +#include "linkdefs.h" #include "platform.h" // strdup uint8_t fillByte; @@ -73,7 +74,7 @@ attr_(warn_unused_result) static bool checkcodesection(void) attr_(warn_unused_result) static bool checkSectionSize(struct Section const *sect, uint32_t size) { - uint32_t maxSize = maxsize[sect->type]; + uint32_t maxSize = sectionTypeInfo[sect->type].size; // If the new size is reasonable, keep going if (size <= maxSize) @@ -232,7 +233,7 @@ static void mergeSections(struct Section *sect, enum SectionType type, uint32_t unsigned int nbSectErrors = 0; if (type != sect->type) - fail("Section already exists but with type %s\n", typeNames[sect->type]); + fail("Section already exists but with type %s\n", sectionTypeInfo[sect->type].name); if (sect->modifier != mod) { fail("Section already declared as %s section\n", sectionModNames[sect->modifier]); @@ -299,7 +300,7 @@ static struct Section *createSection(char const *name, enum SectionType type, /* It is only needed to allocate memory for ROM sections. */ if (sect_HasData(type)) { - sect->data = malloc(maxsize[type]); + sect->data = malloc(sectionTypeInfo[type].size); if (sect->data == NULL) fatalerror("Not enough memory for section: %s\n", strerror(errno)); } else { @@ -325,14 +326,13 @@ static struct Section *getSection(char const *name, enum SectionType type, uint3 if (type != SECTTYPE_ROMX && type != SECTTYPE_VRAM && type != SECTTYPE_SRAM && type != SECTTYPE_WRAMX) error("BANK only allowed for ROMX, WRAMX, SRAM, or VRAM sections\n"); - else if (bank < bankranges[type][0] - || bank > bankranges[type][1]) + else if (bank < sectionTypeInfo[type].firstBank || bank > sectionTypeInfo[type].lastBank) error("%s bank value $%04" PRIx32 " out of range ($%04" PRIx32 " to $%04" - PRIx32 ")\n", typeNames[type], bank, - bankranges[type][0], bankranges[type][1]); + PRIx32 ")\n", sectionTypeInfo[type].name, bank, + sectionTypeInfo[type].firstBank, sectionTypeInfo[type].lastBank); } else if (nbbanks(type) == 1) { // If the section type only has a single bank, implicitly force it - bank = bankranges[type][0]; + bank = sectionTypeInfo[type].firstBank; } if (alignOffset >= 1 << alignment) { @@ -342,10 +342,10 @@ static struct Section *getSection(char const *name, enum SectionType type, uint3 } if (org != (uint32_t)-1) { - if (org < startaddr[type] || org > endaddr(type)) + if (org < sectionTypeInfo[type].startAddr || org > endaddr(type)) error("Section \"%s\"'s fixed address %#" PRIx32 " is outside of range [%#" PRIx16 "; %#" PRIx16 "]\n", - name, org, startaddr[type], endaddr(type)); + name, org, sectionTypeInfo[type].startAddr, endaddr(type)); } if (alignment != 0) { @@ -361,9 +361,9 @@ static struct Section *getSection(char const *name, enum SectionType type, uint3 error("Section \"%s\"'s fixed address doesn't match its alignment\n", name); alignment = 0; /* Ignore it if it's satisfied */ - } else if (startaddr[type] & mask) { + } else if (sectionTypeInfo[type].startAddr & mask) { error("Section \"%s\"'s alignment cannot be attained in %s\n", - name, typeNames[type]); + name, sectionTypeInfo[type].name); alignment = 0; /* Ignore it if it's unattainable */ org = 0; } else if (alignment == 16) { diff --git a/src/link/assign.c b/src/link/assign.c index 0824ca42..b0f6e7b5 100644 --- a/src/link/assign.c +++ b/src/link/assign.c @@ -21,6 +21,7 @@ #include "error.h" #include "helpers.h" +#include "linkdefs.h" struct MemoryLocation { uint16_t address; @@ -54,8 +55,8 @@ static void initFreeSpace(void) if (!memory[type][bank].next) err("Failed to init free space for region %d bank %" PRIu32, type, bank); - memory[type][bank].next->address = startaddr[type]; - memory[type][bank].next->size = maxsize[type]; + memory[type][bank].next->address = sectionTypeInfo[type].startAddr; + memory[type][bank].next->size = sectionTypeInfo[type].size; memory[type][bank].next->next = NULL; memory[type][bank].next->prev = &memory[type][bank]; } @@ -140,13 +141,13 @@ static struct FreeSpace *getPlacement(struct Section const *section, if (curScrambleSRAM > scrambleSRAM) curScrambleSRAM = 0; } else { - location->bank = bankranges[section->type][0]; + location->bank = sectionTypeInfo[section->type].firstBank; } struct FreeSpace *space; for (;;) { /* Switch to the beginning of the next bank */ -#define BANK_INDEX (location->bank - bankranges[section->type][0]) +#define BANK_INDEX (location->bank - sectionTypeInfo[section->type].firstBank) space = memory[section->type][BANK_INDEX].next; if (space) location->address = space->address; @@ -201,7 +202,7 @@ static struct FreeSpace *getPlacement(struct Section const *section, /* Try again in the next bank */ location->bank++; - if (location->bank > bankranges[section->type][1]) + if (location->bank > sectionTypeInfo[section->type].lastBank) return NULL; #undef BANK_INDEX } @@ -225,10 +226,10 @@ static void placeSection(struct Section *section) */ location.address = section->isAddressFixed ? section->org - : startaddr[section->type]; + : sectionTypeInfo[section->type].startAddr; location.bank = section->isBankFixed ? section->bank - : bankranges[section->type][0]; + : sectionTypeInfo[section->type].firstBank; assignSection(section, &location); return; } @@ -314,16 +315,16 @@ static void placeSection(struct Section *section) /* If a section failed to go to several places, nothing we can report */ if (!section->isBankFixed || !section->isAddressFixed) errx("Unable to place \"%s\" (%s section) %s", - section->name, typeNames[section->type], where); + section->name, sectionTypeInfo[section->type].name, where); /* If the section just can't fit the bank, report that */ else if (section->org + section->size > endaddr(section->type) + 1) errx("Unable to place \"%s\" (%s section) %s: section runs past end of region ($%04x > $%04x)", - section->name, typeNames[section->type], where, + section->name, sectionTypeInfo[section->type].name, where, section->org + section->size, endaddr(section->type) + 1); /* Otherwise there is overlap with another section */ else errx("Unable to place \"%s\" (%s section) %s: section overlaps with \"%s\"", - section->name, typeNames[section->type], where, + section->name, sectionTypeInfo[section->type].name, where, out_OverlappingSection(section)->name); } diff --git a/src/link/main.c b/src/link/main.c index 189de2a8..52485185 100644 --- a/src/link/main.c +++ b/src/link/main.c @@ -440,13 +440,13 @@ int main(int argc, char *argv[]) /* Patch the size array depending on command-line options */ if (!is32kMode) - maxsize[SECTTYPE_ROM0] = 0x4000; + sectionTypeInfo[SECTTYPE_ROM0].size = 0x4000; if (!isWRA0Mode) - maxsize[SECTTYPE_WRAM0] = 0x1000; + sectionTypeInfo[SECTTYPE_WRAM0].size = 0x1000; /* Patch the bank ranges array depending on command-line options */ if (isDmgMode) - bankranges[SECTTYPE_VRAM][1] = BANK_MIN_VRAM; + sectionTypeInfo[SECTTYPE_VRAM].lastBank = 0; /* Read all object files first, */ for (obj_Setup(argc - curArgIndex); curArgIndex < argc; curArgIndex++) diff --git a/src/link/output.c b/src/link/output.c index a7794e6c..1fcbf0ee 100644 --- a/src/link/output.c +++ b/src/link/output.c @@ -72,7 +72,7 @@ void out_AddSection(struct Section const *section) [SECTTYPE_HRAM] = 1 }; - uint32_t targetBank = section->bank - bankranges[section->type][0]; + uint32_t targetBank = section->bank - sectionTypeInfo[section->type].firstBank; uint32_t minNbBanks = targetBank + 1; if (minNbBanks > maxNbBanks[section->type]) @@ -113,7 +113,7 @@ struct Section const *out_OverlappingSection(struct Section const *section) { struct SortedSections *banks = sections[section->type].banks; struct SortedSection *ptr = - banks[section->bank - bankranges[section->type][0]].sections; + banks[section->bank - sectionTypeInfo[section->type].firstBank].sections; while (ptr) { if (ptr->section->org < section->org + section->size @@ -166,7 +166,7 @@ static uint32_t checkOverlaySize(void) static void coverOverlayBanks(uint32_t nbOverlayBanks) { /* 2 if is32kMode, 1 otherwise */ - uint32_t nbRom0Banks = maxsize[SECTTYPE_ROM0] / BANK_SIZE; + uint32_t nbRom0Banks = sectionTypeInfo[SECTTYPE_ROM0].size / BANK_SIZE; /* Discount ROM0 banks to avoid outputting too much */ uint32_t nbUncoveredBanks = nbOverlayBanks - nbRom0Banks > sections[SECTTYPE_ROMX].nbBanks ? nbOverlayBanks - nbRom0Banks @@ -247,11 +247,11 @@ static void writeROM(void) if (outputFile) { writeBank(sections[SECTTYPE_ROM0].banks ? sections[SECTTYPE_ROM0].banks[0].sections : NULL, - startaddr[SECTTYPE_ROM0], maxsize[SECTTYPE_ROM0]); + sectionTypeInfo[SECTTYPE_ROM0].startAddr, sectionTypeInfo[SECTTYPE_ROM0].size); for (uint32_t i = 0 ; i < sections[SECTTYPE_ROMX].nbBanks; i++) writeBank(sections[SECTTYPE_ROMX].banks[i].sections, - startaddr[SECTTYPE_ROMX], maxsize[SECTTYPE_ROMX]); + sectionTypeInfo[SECTTYPE_ROMX].startAddr, sectionTypeInfo[SECTTYPE_ROMX].size); } closeFile(outputFile); @@ -345,7 +345,7 @@ static void writeSymBank(struct SortedSections const *bankSections, qsort(symList, nbSymbols, sizeof(*symList), compareSymbols); - uint32_t symBank = bank + bankranges[type][0]; + uint32_t symBank = bank + sectionTypeInfo[type].firstBank; for (uint32_t i = 0; i < nbSymbols; i++) { struct SortedSymbol *sym = &symList[i]; @@ -371,8 +371,8 @@ static uint16_t writeMapBank(struct SortedSections const *sectList, struct SortedSection const *section = sectList->sections; struct SortedSection const *zeroLenSection = sectList->zeroLenSections; - fprintf(mapFile, "%s bank #%" PRIu32 ":\n", typeNames[type], - bank + bankranges[type][0]); + fprintf(mapFile, "%s bank #%" PRIu32 ":\n", sectionTypeInfo[type].name, + bank + sectionTypeInfo[type].firstBank); uint16_t used = 0; @@ -413,7 +413,7 @@ static uint16_t writeMapBank(struct SortedSections const *sectList, if (used == 0) { fputs(" EMPTY\n\n", mapFile); } else { - uint16_t slack = maxsize[type] - used; + uint16_t slack = sectionTypeInfo[type].size - used; fprintf(mapFile, " SLACK: $%04" PRIx16 " byte%s\n\n", slack, slack == 1 ? "" : "s"); @@ -442,7 +442,7 @@ static void writeMapUsed(uint32_t usedMap[MIN_NB_ELMS(SECTTYPE_INVALID)]) if (sections[type].nbBanks > 0) { fprintf(mapFile, " %s: $%04" PRIx32 " byte%s in %" PRIu32 " bank%s\n", - typeNames[type], usedMap[type], usedMap[type] == 1 ? "" : "s", + sectionTypeInfo[type].name, usedMap[type], usedMap[type] == 1 ? "" : "s", sections[type].nbBanks, sections[type].nbBanks == 1 ? "" : "s"); } } diff --git a/src/link/script.c b/src/link/script.c index 08c6dc62..97c43422 100644 --- a/src/link/script.c +++ b/src/link/script.c @@ -18,6 +18,7 @@ #include "link/section.h" #include "error.h" +#include "linkdefs.h" FILE *linkerScript; char *includeFileName; @@ -299,7 +300,7 @@ static struct LinkerScriptToken *nextToken(void) if (token.type == TOKEN_INVALID) { /* Try to match a bank specifier */ for (enum SectionType type = 0; type < SECTTYPE_INVALID; type++) { - if (!strcmp(typeNames[type], str)) { + if (!strcmp(sectionTypeInfo[type].name, str)) { token.type = TOKEN_BANK; token.attr.secttype = type; break; @@ -376,7 +377,7 @@ struct SectionPlacement *script_NextSection(void) for (enum SectionType i = 0; i < SECTTYPE_INVALID; i++) { curaddr[i] = malloc(sizeof(*curaddr[i]) * nbbanks(i)); for (uint32_t b = 0; b < nbbanks(i); b++) - curaddr[i][b] = startaddr[i]; + curaddr[i][b] = sectionTypeInfo[i].startAddr; } placement.type = SECTTYPE_INVALID; @@ -394,12 +395,12 @@ struct SectionPlacement *script_NextSection(void) if (placement.type != SECTTYPE_INVALID) { if (curaddr[placement.type][bankID] > endaddr(placement.type) + 1) errx("%s(%" PRIu32 "): Sections would extend past the end of %s ($%04" PRIx16 " > $%04" PRIx16 ")", - linkerScriptName, lineNo, typeNames[placement.type], + linkerScriptName, lineNo, sectionTypeInfo[placement.type].name, curaddr[placement.type][bankID], endaddr(placement.type)); - if (curaddr[placement.type][bankID] < startaddr[placement.type]) + if (curaddr[placement.type][bankID] < sectionTypeInfo[placement.type].startAddr) errx("%s(%" PRIu32 "): PC underflowed ($%04" PRIx16 " < $%04" PRIx16 ")", linkerScriptName, lineNo, - curaddr[placement.type][bankID], startaddr[placement.type]); + curaddr[placement.type][bankID], sectionTypeInfo[placement.type].startAddr); } switch (parserState) { @@ -483,17 +484,17 @@ struct SectionPlacement *script_NextSection(void) errx("%s(%" PRIu32 "): Didn't specify a bank number", linkerScriptName, lineNo); else if (!hasArg) - arg = bankranges[placement.type][0]; - else if (arg < bankranges[placement.type][0]) + arg = sectionTypeInfo[placement.type].firstBank; + else if (arg < sectionTypeInfo[placement.type].firstBank) errx("%s(%" PRIu32 "): specified bank number is too low (%" PRIu32 " < %" PRIu32 ")", linkerScriptName, lineNo, - arg, bankranges[placement.type][0]); - else if (arg > bankranges[placement.type][1]) + arg, sectionTypeInfo[placement.type].firstBank); + else if (arg > sectionTypeInfo[placement.type].lastBank) errx("%s(%" PRIu32 "): specified bank number is too high (%" PRIu32 " > %" PRIu32 ")", linkerScriptName, lineNo, - arg, bankranges[placement.type][1]); + arg, sectionTypeInfo[placement.type].lastBank); bank = arg; - bankID = arg - bankranges[placement.type][0]; + bankID = arg - sectionTypeInfo[placement.type].firstBank; } /* If we read a token we shouldn't have... */ diff --git a/src/link/section.c b/src/link/section.c index f87b2889..265c4fdb 100644 --- a/src/link/section.c +++ b/src/link/section.c @@ -17,6 +17,7 @@ #include "error.h" #include "hashmap.h" +#include "linkdefs.h" HashMap sections; @@ -133,7 +134,7 @@ static void mergeSections(struct Section *target, struct Section *other, enum Se if (target->type != other->type) errx("Section \"%s\" is defined with conflicting types %s and %s", - other->name, typeNames[target->type], typeNames[other->type]); + other->name, sectionTypeInfo[target->type].name, sectionTypeInfo[other->type].name); if (other->isBankFixed) { if (!target->isBankFixed) { @@ -207,7 +208,7 @@ void sect_AddSection(struct Section *section) mergeSections(other, section, section->modifier); } else if (section->modifier == SECTION_UNION && sect_HasData(section->type)) { errx("Section \"%s\" is of type %s, which cannot be unionized", - section->name, typeNames[section->type]); + section->name, sectionTypeInfo[section->type].name); } else { /* If not, add it */ hash_AddElement(sections, section->name, section); @@ -261,11 +262,11 @@ static void doSanityChecks(struct Section *section, void *ptr) section->isAlignFixed = false; /* Too large an alignment may not be satisfiable */ - if (section->isAlignFixed && (section->alignMask & startaddr[section->type])) + if (section->isAlignFixed && (section->alignMask & sectionTypeInfo[section->type].startAddr)) error(NULL, 0, "%s: %s sections cannot be aligned to $%04x bytes", - section->name, typeNames[section->type], section->alignMask + 1); + section->name, sectionTypeInfo[section->type].name, section->alignMask + 1); - uint32_t minbank = bankranges[section->type][0], maxbank = bankranges[section->type][1]; + uint32_t minbank = sectionTypeInfo[section->type].firstBank, maxbank = sectionTypeInfo[section->type].lastBank; if (section->isBankFixed && section->bank < minbank && section->bank > maxbank) error(NULL, 0, minbank == maxbank @@ -274,9 +275,9 @@ static void doSanityChecks(struct Section *section, void *ptr) section->name, section->bank, minbank, maxbank); /* Check if section has a chance to be placed */ - if (section->size > maxsize[section->type]) + if (section->size > sectionTypeInfo[section->type].size) error(NULL, 0, "Section \"%s\" is bigger than the max size for that type: %#" PRIx16 " > %#" PRIx16, - section->name, section->size, maxsize[section->type]); + section->name, section->size, sectionTypeInfo[section->type].size); /* Translate loose constraints to strong ones when they're equivalent */ @@ -295,11 +296,11 @@ static void doSanityChecks(struct Section *section, void *ptr) } /* Ensure the target address is valid */ - if (section->org < startaddr[section->type] + if (section->org < sectionTypeInfo[section->type].startAddr || section->org > endaddr(section->type)) error(NULL, 0, "Section \"%s\"'s fixed address %#" PRIx16 " is outside of range [%#" PRIx16 "; %#" PRIx16 "]", section->name, section->org, - startaddr[section->type], endaddr(section->type)); + sectionTypeInfo[section->type].startAddr, endaddr(section->type)); if (section->org + section->size > endaddr(section->type) + 1) error(NULL, 0, "Section \"%s\"'s end address %#x is greater than last address %#x", diff --git a/src/linkdefs.c b/src/linkdefs.c index d45c0beb..2765f642 100644 --- a/src/linkdefs.c +++ b/src/linkdefs.c @@ -1,48 +1,65 @@ #include "linkdefs.h" -uint16_t startaddr[] = { - [SECTTYPE_ROM0] = 0x0000, - [SECTTYPE_ROMX] = 0x4000, - [SECTTYPE_VRAM] = 0x8000, - [SECTTYPE_SRAM] = 0xA000, - [SECTTYPE_WRAM0] = 0xC000, - [SECTTYPE_WRAMX] = 0xD000, - [SECTTYPE_OAM] = 0xFE00, - [SECTTYPE_HRAM] = 0xFF80 -}; - -uint16_t maxsize[] = { - [SECTTYPE_ROM0] = 0x8000, // patched to 0x4000 if !is32kMode - [SECTTYPE_ROMX] = 0x4000, - [SECTTYPE_VRAM] = 0x2000, - [SECTTYPE_SRAM] = 0x2000, - [SECTTYPE_WRAM0] = 0x2000, // patched to 0x1000 if !isWRA0Mode - [SECTTYPE_WRAMX] = 0x1000, - [SECTTYPE_OAM] = 0x00A0, - [SECTTYPE_HRAM] = 0x007F -}; - -uint32_t bankranges[][2] = { - [SECTTYPE_ROM0] = {BANK_MIN_ROM0, BANK_MAX_ROM0}, - [SECTTYPE_ROMX] = {BANK_MIN_ROMX, BANK_MAX_ROMX}, - [SECTTYPE_VRAM] = {BANK_MIN_VRAM, BANK_MAX_VRAM}, - [SECTTYPE_SRAM] = {BANK_MIN_SRAM, BANK_MAX_SRAM}, - [SECTTYPE_WRAM0] = {BANK_MIN_WRAM0, BANK_MAX_WRAM0}, - [SECTTYPE_WRAMX] = {BANK_MIN_WRAMX, BANK_MAX_WRAMX}, - [SECTTYPE_OAM] = {BANK_MIN_OAM, BANK_MAX_OAM}, - [SECTTYPE_HRAM] = {BANK_MIN_HRAM, BANK_MAX_HRAM} -}; - -char const * const typeNames[] = { - [SECTTYPE_ROM0] = "ROM0", - [SECTTYPE_ROMX] = "ROMX", - [SECTTYPE_VRAM] = "VRAM", - [SECTTYPE_SRAM] = "SRAM", - [SECTTYPE_WRAM0] = "WRAM0", - [SECTTYPE_WRAMX] = "WRAMX", - [SECTTYPE_OAM] = "OAM", - [SECTTYPE_HRAM] = "HRAM" +// The default values are the most lax, as they are used as-is by RGBASM; only RGBLINK has the full info, +// so RGBASM's job is only to catch unconditional errors earlier. +struct SectionTypeInfo sectionTypeInfo[SECTTYPE_INVALID] = { + [SECTTYPE_ROM0] = { + .name = "ROM0", + .startAddr = 0x0000, + .size = 0x8000, // Patched to 0x4000 if !is32kMode + .firstBank = 0, + .lastBank = 0, + }, + [SECTTYPE_ROMX] = { + .name = "ROMX", + .startAddr = 0x4000, + .size = 0x4000, + .firstBank = 1, + .lastBank = 65535, + }, + [SECTTYPE_VRAM] = { + .name = "VRAM", + .startAddr = 0x8000, + .size = 0x2000, + .firstBank = 0, + .lastBank = 1, // Patched to 0 if isDmgMode + }, + [SECTTYPE_SRAM] = { + .name = "SRAM", + .startAddr = 0xA000, + .size = 0x2000, + .firstBank = 0, + .lastBank = 255, + }, + [SECTTYPE_WRAM0] = { + .name = "WRAM0", + .startAddr = 0xC000, + .size = 0x2000, // Patched to 0x1000 if !isWRA0Mode + .firstBank = 0, + .lastBank = 0, + }, + [SECTTYPE_WRAMX] = { + .name = "WRAMX", + .startAddr = 0xD000, + .size = 0x1000, + .firstBank = 1, + .lastBank = 7, + }, + [SECTTYPE_OAM] = { + .name = "OAM", + .startAddr = 0xFE00, + .size = 0x00A0, + .firstBank = 0, + .lastBank = 0, + }, + [SECTTYPE_HRAM] = { + .name = "HRAM", + .startAddr = 0xFF80, + .size = 0x007F, + .firstBank = 0, + .lastBank = 0, + }, }; char const * const sectionModNames[] = {