mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-24 12:02:08 +00:00
Allow specifying offset in addition to alignment
This commit is contained in:
@@ -132,7 +132,8 @@ static bool isLocationSuitable(struct Section const *section,
|
||||
if (section->isAddressFixed && section->org != location->address)
|
||||
return false;
|
||||
|
||||
if (section->isAlignFixed && location->address & section->alignMask)
|
||||
if (section->isAlignFixed
|
||||
&& ((location->address - section->alignOfs) & section->alignMask))
|
||||
return false;
|
||||
|
||||
if (location->address < freeSpace->address)
|
||||
@@ -183,8 +184,13 @@ static struct FreeSpace *getPlacement(struct Section const *section,
|
||||
space = NULL;
|
||||
} else if (section->isAlignFixed) {
|
||||
/* Move to next aligned location */
|
||||
/* Move back to alignment boundary */
|
||||
location->address -= section->alignOfs;
|
||||
/* Ensure we're there (e.g. on first check) */
|
||||
location->address &= ~section->alignMask;
|
||||
location->address += section->alignMask + 1;
|
||||
/* Go to next align boundary and add offset */
|
||||
location->address += section->alignMask + 1
|
||||
+ section->alignOfs;
|
||||
} else {
|
||||
/* Any location is fine, so, next free block */
|
||||
space = space->next;
|
||||
@@ -309,8 +315,8 @@ static void placeSection(struct Section *section)
|
||||
if (section->isAddressFixed)
|
||||
snprintf(where, 64, "at address $%04x", section->org);
|
||||
else if (section->isAlignFixed)
|
||||
snprintf(where, 64, "with align mask %x",
|
||||
~section->alignMask);
|
||||
snprintf(where, 64, "with align mask %x and offset %u",
|
||||
~section->alignMask, section->alignOfs);
|
||||
else
|
||||
strcpy(where, "anywhere");
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ static void readSection(FILE *file, struct Section *section,
|
||||
char const *fileName, struct Section *fileSections[])
|
||||
{
|
||||
int32_t tmp;
|
||||
uint8_t type;
|
||||
uint8_t byte;
|
||||
|
||||
tryReadstr(section->name, file, "%s: Cannot read section name: %s",
|
||||
fileName);
|
||||
@@ -265,24 +265,34 @@ static void readSection(FILE *file, struct Section *section,
|
||||
errx(1, "\"%s\"'s section size (%d) is invalid", section->name,
|
||||
tmp);
|
||||
section->size = tmp;
|
||||
tryGetc(type, file, "%s: Cannot read \"%s\"'s type: %s",
|
||||
tryGetc(byte, file, "%s: Cannot read \"%s\"'s type: %s",
|
||||
fileName, section->name);
|
||||
section->type = type & 0x7F;
|
||||
section->isUnion = type >> 7;
|
||||
section->type = byte & 0x7F;
|
||||
section->isUnion = byte >> 7;
|
||||
tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s org: %s",
|
||||
fileName, section->name);
|
||||
section->isAddressFixed = tmp >= 0;
|
||||
if (tmp > UINT16_MAX)
|
||||
errx(1, "\"%s\"'s org' is too large (%d)", section->name, tmp);
|
||||
if (tmp > UINT16_MAX) {
|
||||
error("\"%s\"'s org is too large (%d)", section->name, tmp);
|
||||
tmp = UINT16_MAX;
|
||||
}
|
||||
section->org = tmp;
|
||||
tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s bank: %s",
|
||||
fileName, section->name);
|
||||
section->isBankFixed = tmp >= 0;
|
||||
section->bank = tmp;
|
||||
tryGetc(tmp, file, "%s: Cannot read \"%s\"'s alignment: %s",
|
||||
tryGetc(byte, file, "%s: Cannot read \"%s\"'s alignment: %s",
|
||||
fileName, section->name);
|
||||
section->isAlignFixed = tmp != 0;
|
||||
section->alignMask = (1 << tmp) - 1;
|
||||
section->isAlignFixed = byte != 0;
|
||||
section->alignMask = (1 << byte) - 1;
|
||||
tryReadlong(tmp, file, "%s: Cannot read \"%s\"'s alignment offset: %s",
|
||||
fileName, section->name);
|
||||
if (tmp > UINT16_MAX) {
|
||||
error("\"%s\"'s alignment offset is too large (%d)",
|
||||
section->name, tmp);
|
||||
tmp = UINT16_MAX;
|
||||
}
|
||||
section->alignOfs = tmp;
|
||||
|
||||
if (sect_HasData(section->type)) {
|
||||
/* Ensure we never allocate 0 bytes */
|
||||
|
||||
@@ -48,21 +48,28 @@ static void mergeSections(struct Section *target, struct Section *other)
|
||||
errx(1, "Section \"%s\" is defined with conflicting addresses $%x and $%x",
|
||||
other->name, target->org, other->org);
|
||||
} else if (target->isAlignFixed) {
|
||||
if (other->org & target->alignMask)
|
||||
errx(1, "Section \"%s\" is defined with conflicting %u-byte alignment and address $%x",
|
||||
if ((other->org - target->alignOfs) & target->alignMask)
|
||||
errx(1, "Section \"%s\" is defined with conflicting %u-byte alignment (offset %u) and address $%x",
|
||||
other->name, target->alignMask + 1,
|
||||
other->org);
|
||||
target->alignOfs, other->org);
|
||||
}
|
||||
target->isAddressFixed = true;
|
||||
target->org = other->org;
|
||||
} else if (other->isAlignFixed) {
|
||||
if (target->isAddressFixed) {
|
||||
if (target->org & other->alignMask)
|
||||
errx(1, "Section \"%s\" is defined with conflicting address $%x and %u-byte alignment",
|
||||
if ((target->org - other->alignOfs) & other->alignMask)
|
||||
errx(1, "Section \"%s\" is defined with conflicting address $%x and %u-byte alignment (offset %u)",
|
||||
other->name, target->org,
|
||||
other->alignMask + 1);
|
||||
other->alignMask + 1, other->alignOfs);
|
||||
} else if (target->isAlignFixed
|
||||
&& (other->alignMask & target->alignOfs)
|
||||
!= (target->alignMask & other->alignOfs)) {
|
||||
errx(1, "Section \"%s\" is defined with conflicting %u-byte alignment (offset %u) and %u-byte alignment (offset %u)",
|
||||
other->name, target->alignMask + 1,
|
||||
target->alignOfs, other->alignMask + 1,
|
||||
other->alignOfs);
|
||||
} else if (!target->isAlignFixed
|
||||
|| other->alignMask > target->alignMask) {
|
||||
|| (other->alignMask > target->alignMask)) {
|
||||
target->isAlignFixed = true;
|
||||
target->alignMask = other->alignMask;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user