shithub: rgbds

Download patch

ref: 9ec8186ac6e6dd9715e542ecf50ae6c29ee6f7aa
parent: ab9945c1eefb4a3b64365e10ff6e8cf610f7c52a
author: ISSOtm <[email protected]>
date: Tue Jul 19 14:59:51 EDT 2022

Switch `linkdefs` from scattered arrays to an array of structs

The info is better organized this way

--- a/include/linkdefs.h
+++ b/include/linkdefs.h
@@ -79,14 +79,15 @@
 	SECTTYPE_INVALID
 };
 
-enum SectionModifier {
-	SECTION_NORMAL,
-	SECTION_UNION,
-	SECTION_FRAGMENT
-};
+// 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];
 
-extern char const * const sectionModNames[];
-
 /**
  * Tells whether a section has data in its object file definition,
  * depending on type.
@@ -99,42 +100,6 @@
 	return type == SECTTYPE_ROM0 || type == SECTTYPE_ROMX;
 }
 
-enum ExportLevel {
-	SYMTYPE_LOCAL,
-	SYMTYPE_IMPORT,
-	SYMTYPE_EXPORT
-};
-
-enum PatchType {
-	PATCHTYPE_BYTE,
-	PATCHTYPE_WORD,
-	PATCHTYPE_LONG,
-	PATCHTYPE_JR,
-
-	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
@@ -141,7 +106,7 @@
  */
 static inline uint16_t endaddr(enum SectionType type)
 {
-	return startaddr[type] + maxsize[type] - 1;
+	return sectionTypeInfo[type].startAddr + sectionTypeInfo[type].size - 1;
 }
 
 /**
@@ -150,9 +115,30 @@
  */
 static inline uint32_t nbbanks(enum SectionType type)
 {
-	return bankranges[type][1] - bankranges[type][0] + 1;
+	return sectionTypeInfo[type].lastBank - sectionTypeInfo[type].firstBank + 1;
 }
 
-extern char const * const typeNames[SECTTYPE_INVALID];
+enum SectionModifier {
+	SECTION_NORMAL,
+	SECTION_UNION,
+	SECTION_FRAGMENT
+};
+
+extern char const * const sectionModNames[];
+
+enum ExportLevel {
+	SYMTYPE_LOCAL,
+	SYMTYPE_IMPORT,
+	SYMTYPE_EXPORT
+};
+
+enum PatchType {
+	PATCHTYPE_BYTE,
+	PATCHTYPE_WORD,
+	PATCHTYPE_LONG,
+	PATCHTYPE_JR,
+
+	PATCHTYPE_INVALID
+};
 
 #endif /* RGBDS_LINKDEFS_H */
--- 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 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 @@
 	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 @@
 
 	/* 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 @@
 		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 @@
 	}
 
 	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 @@
 				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) {
--- 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 @@
 			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 @@
 		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 @@
 
 		/* 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 @@
 		 */
 		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 @@
 	/* 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);
 }
 
--- a/src/link/main.c
+++ b/src/link/main.c
@@ -440,13 +440,13 @@
 
 	/* 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++)
--- a/src/link/output.c
+++ b/src/link/output.c
@@ -72,7 +72,7 @@
 		[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 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 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 @@
 	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 @@
 
 	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 @@
 	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 @@
 	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 @@
 
 		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");
 		}
 	}
--- 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 @@
 		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 @@
 		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 @@
 		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 @@
 						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... */
--- 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 @@
 
 	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 @@
 			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 @@
 		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 @@
 		     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 @@
 		}
 
 		/* 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",
--- 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[] = {