mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-21 02:32:06 +00:00
Use std::vector for RPN expressions
This commit is contained in:
@@ -23,8 +23,7 @@ struct Patch {
|
|||||||
uint32_t pcSectionID;
|
uint32_t pcSectionID;
|
||||||
uint32_t pcOffset;
|
uint32_t pcOffset;
|
||||||
enum PatchType type;
|
enum PatchType type;
|
||||||
uint32_t rpnSize;
|
std::vector<uint8_t> rpnExpression;
|
||||||
uint8_t *rpnExpression;
|
|
||||||
|
|
||||||
struct Section const *pcSection;
|
struct Section const *pcSection;
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -248,7 +248,7 @@ static void readSymbol(FILE *file, struct Symbol *symbol,
|
|||||||
static void readPatch(FILE *file, struct Patch *patch, char const *fileName, char const *sectName,
|
static void readPatch(FILE *file, struct Patch *patch, char const *fileName, char const *sectName,
|
||||||
uint32_t i, struct FileStackNode fileNodes[])
|
uint32_t i, struct FileStackNode fileNodes[])
|
||||||
{
|
{
|
||||||
uint32_t nodeID;
|
uint32_t nodeID, rpnSize;
|
||||||
enum PatchType type;
|
enum PatchType type;
|
||||||
|
|
||||||
tryReadlong(nodeID, file,
|
tryReadlong(nodeID, file,
|
||||||
@@ -271,18 +271,15 @@ static void readPatch(FILE *file, struct Patch *patch, char const *fileName, cha
|
|||||||
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s type: %s",
|
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s type: %s",
|
||||||
fileName, sectName, i);
|
fileName, sectName, i);
|
||||||
patch->type = type;
|
patch->type = type;
|
||||||
tryReadlong(patch->rpnSize, file,
|
tryReadlong(rpnSize, file,
|
||||||
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s RPN size: %s",
|
"%s: Unable to read \"%s\"'s patch #%" PRIu32 "'s RPN size: %s",
|
||||||
fileName, sectName, i);
|
fileName, sectName, i);
|
||||||
|
|
||||||
patch->rpnExpression = (uint8_t *)malloc(sizeof(*patch->rpnExpression) * patch->rpnSize);
|
patch->rpnExpression.resize(rpnSize);
|
||||||
if (!patch->rpnExpression)
|
size_t nbElementsRead = fread(&patch->rpnExpression[0], sizeof(patch->rpnExpression[0]),
|
||||||
err("%s: Failed to alloc \"%s\"'s patch #%" PRIu32 "'s RPN expression",
|
rpnSize, file);
|
||||||
fileName, sectName, i);
|
|
||||||
size_t nbElementsRead = fread(patch->rpnExpression, sizeof(*patch->rpnExpression),
|
|
||||||
patch->rpnSize, file);
|
|
||||||
|
|
||||||
if (nbElementsRead != patch->rpnSize)
|
if (nbElementsRead != rpnSize)
|
||||||
errx("%s: Cannot read \"%s\"'s patch #%" PRIu32 "'s RPN expression: %s",
|
errx("%s: Cannot read \"%s\"'s patch #%" PRIu32 "'s RPN expression: %s",
|
||||||
fileName, sectName, i,
|
fileName, sectName, i,
|
||||||
feof(file) ? "Unexpected end of file" : strerror(errno));
|
feof(file) ? "Unexpected end of file" : strerror(errno));
|
||||||
@@ -668,8 +665,6 @@ static void freeSection(struct Section *section)
|
|||||||
free(section->name);
|
free(section->name);
|
||||||
if (sect_HasData(section->type)) {
|
if (sect_HasData(section->type)) {
|
||||||
free(section->data);
|
free(section->data);
|
||||||
for (struct Patch &patch : *section->patches)
|
|
||||||
free(patch.rpnExpression);
|
|
||||||
delete section->patches;
|
delete section->patches;
|
||||||
}
|
}
|
||||||
free(section->symbols);
|
free(section->symbols);
|
||||||
@@ -706,8 +701,6 @@ void obj_Cleanup(void)
|
|||||||
free(list.symbolList);
|
free(list.symbolList);
|
||||||
}
|
}
|
||||||
|
|
||||||
for (struct Assertion &assert : assertions) {
|
for (struct Assertion &assert : assertions)
|
||||||
free(assert.patch.rpnExpression);
|
|
||||||
free(assert.message);
|
free(assert.message);
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -83,8 +83,8 @@ static int32_t computeRPNExpr(struct Patch const *patch,
|
|||||||
// Small shortcut to avoid a lot of repetition
|
// Small shortcut to avoid a lot of repetition
|
||||||
#define popRPN() popRPN(patch->src, patch->lineNo)
|
#define popRPN() popRPN(patch->src, patch->lineNo)
|
||||||
|
|
||||||
uint8_t const *expression = patch->rpnExpression;
|
uint8_t const *expression = &patch->rpnExpression[0];
|
||||||
int32_t size = patch->rpnSize;
|
int32_t size = (int32_t)patch->rpnExpression.size();
|
||||||
|
|
||||||
rpnStack.clear();
|
rpnStack.clear();
|
||||||
|
|
||||||
|
|||||||
@@ -598,14 +598,6 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file) {
|
|||||||
for (uint8_t i = 0; i < nbBaseBytes; ++i)
|
for (uint8_t i = 0; i < nbBaseBytes; ++i)
|
||||||
baseValue = baseValue | data[offset + i] << (8 * i);
|
baseValue = baseValue | data[offset + i] << (8 * i);
|
||||||
|
|
||||||
// Extra size that must be reserved for additional operators
|
|
||||||
#define RPN_EXTRA_SIZE (5 + 1 + 5 + 1 + 5 + 1) // >> 8 & $FF, then + <baseValue>
|
|
||||||
#define allocPatch(size) do { \
|
|
||||||
patch.rpnSize = (size); \
|
|
||||||
patch.rpnExpression = (uint8_t *)malloc(patch.rpnSize + RPN_EXTRA_SIZE); \
|
|
||||||
if (!patch.rpnExpression) \
|
|
||||||
fatal(where, lineNo, "Failed to alloc RPN expression: %s", strerror(errno)); \
|
|
||||||
} while (0)
|
|
||||||
// Bit 4 specifies signedness, but I don't think that matters?
|
// Bit 4 specifies signedness, but I don't think that matters?
|
||||||
// Generate a RPN expression from the info and flags
|
// Generate a RPN expression from the info and flags
|
||||||
if (flags & 1 << RELOC_ISSYM) {
|
if (flags & 1 << RELOC_ISSYM) {
|
||||||
@@ -626,22 +618,22 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file) {
|
|||||||
if (idx == nbSymbols)
|
if (idx == nbSymbols)
|
||||||
fatal(where, lineNo, "\"%s\" is missing a reference to \"%s\"",
|
fatal(where, lineNo, "\"%s\" is missing a reference to \"%s\"",
|
||||||
sym->name, &sym->name[1]);
|
sym->name, &sym->name[1]);
|
||||||
allocPatch(5);
|
patch.rpnExpression.resize(5);
|
||||||
patch.rpnExpression[0] = RPN_BANK_SYM;
|
patch.rpnExpression[0] = RPN_BANK_SYM;
|
||||||
patch.rpnExpression[1] = idx;
|
patch.rpnExpression[1] = idx;
|
||||||
patch.rpnExpression[2] = idx >> 8;
|
patch.rpnExpression[2] = idx >> 8;
|
||||||
patch.rpnExpression[3] = idx >> 16;
|
patch.rpnExpression[3] = idx >> 16;
|
||||||
patch.rpnExpression[4] = idx >> 24;
|
patch.rpnExpression[4] = idx >> 24;
|
||||||
} else if (sym->name[0] == 'l' && sym->name[1] == '_') {
|
} else if (sym->name[0] == 'l' && sym->name[1] == '_') {
|
||||||
allocPatch(1 + strlen(&sym->name[2]) + 1);
|
patch.rpnExpression.resize(1 + strlen(&sym->name[2]) + 1);
|
||||||
patch.rpnExpression[0] = RPN_SIZEOF_SECT;
|
patch.rpnExpression[0] = RPN_SIZEOF_SECT;
|
||||||
strcpy((char *)&patch.rpnExpression[1], &sym->name[2]);
|
strcpy((char *)&patch.rpnExpression[1], &sym->name[2]);
|
||||||
} else if (sym->name[0] == 's' && sym->name[1] == '_') {
|
} else if (sym->name[0] == 's' && sym->name[1] == '_') {
|
||||||
allocPatch(1 + strlen(&sym->name[2]) + 1);
|
patch.rpnExpression.resize(1 + strlen(&sym->name[2]) + 1);
|
||||||
patch.rpnExpression[0] = RPN_STARTOF_SECT;
|
patch.rpnExpression[0] = RPN_STARTOF_SECT;
|
||||||
strcpy((char *)&patch.rpnExpression[1], &sym->name[2]);
|
strcpy((char *)&patch.rpnExpression[1], &sym->name[2]);
|
||||||
} else {
|
} else {
|
||||||
allocPatch(5);
|
patch.rpnExpression.resize(5);
|
||||||
patch.rpnExpression[0] = RPN_SYM;
|
patch.rpnExpression[0] = RPN_SYM;
|
||||||
patch.rpnExpression[1] = idx;
|
patch.rpnExpression[1] = idx;
|
||||||
patch.rpnExpression[2] = idx >> 8;
|
patch.rpnExpression[2] = idx >> 8;
|
||||||
@@ -674,25 +666,18 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file) {
|
|||||||
// current size.
|
// current size.
|
||||||
if (other)
|
if (other)
|
||||||
baseValue += other->size;
|
baseValue += other->size;
|
||||||
allocPatch(1 + strlen(name) + 1);
|
patch.rpnExpression.resize(1 + strlen(name) + 1);
|
||||||
patch.rpnSize = 1 + strlen(name) + 1;
|
|
||||||
patch.rpnExpression = (uint8_t *)malloc(patch.rpnSize + RPN_EXTRA_SIZE);
|
|
||||||
if (!patch.rpnExpression)
|
|
||||||
fatal(where, lineNo, "Failed to alloc RPN expression: %s",
|
|
||||||
strerror(errno));
|
|
||||||
patch.rpnExpression[0] = RPN_STARTOF_SECT;
|
patch.rpnExpression[0] = RPN_STARTOF_SECT;
|
||||||
// The cast is fine, it's just different signedness
|
// The cast is fine, it's just different signedness
|
||||||
strcpy((char *)&patch.rpnExpression[1], name);
|
strcpy((char *)&patch.rpnExpression[1], name);
|
||||||
}
|
}
|
||||||
#undef allocPatch
|
|
||||||
|
|
||||||
patch.rpnExpression[patch.rpnSize] = RPN_CONST;
|
patch.rpnExpression.push_back(RPN_CONST);
|
||||||
patch.rpnExpression[patch.rpnSize + 1] = baseValue;
|
patch.rpnExpression.push_back(baseValue);
|
||||||
patch.rpnExpression[patch.rpnSize + 2] = baseValue >> 8;
|
patch.rpnExpression.push_back(baseValue >> 8);
|
||||||
patch.rpnExpression[patch.rpnSize + 3] = baseValue >> 16;
|
patch.rpnExpression.push_back(baseValue >> 16);
|
||||||
patch.rpnExpression[patch.rpnSize + 4] = baseValue >> 24;
|
patch.rpnExpression.push_back(baseValue >> 24);
|
||||||
patch.rpnExpression[patch.rpnSize + 5] = RPN_ADD;
|
patch.rpnExpression.push_back(RPN_ADD);
|
||||||
patch.rpnSize += 5 + 1;
|
|
||||||
|
|
||||||
if (patch.type == PATCHTYPE_BYTE) {
|
if (patch.type == PATCHTYPE_BYTE) {
|
||||||
// Despite the flag's name, as soon as it is set, 3 bytes
|
// Despite the flag's name, as soon as it is set, 3 bytes
|
||||||
@@ -713,30 +698,27 @@ void sdobj_ReadFile(struct FileStackNode const *where, FILE *file) {
|
|||||||
patch.type = PATCHTYPE_JR;
|
patch.type = PATCHTYPE_JR;
|
||||||
// TODO: check the other flags?
|
// TODO: check the other flags?
|
||||||
} else if (flags & 1 << RELOC_EXPR24 && flags & 1 << RELOC_BANKBYTE) {
|
} else if (flags & 1 << RELOC_EXPR24 && flags & 1 << RELOC_BANKBYTE) {
|
||||||
patch.rpnExpression[patch.rpnSize] = RPN_CONST;
|
patch.rpnExpression.push_back(RPN_CONST);
|
||||||
patch.rpnExpression[patch.rpnSize + 1] = 16;
|
patch.rpnExpression.push_back(16);
|
||||||
patch.rpnExpression[patch.rpnSize + 2] = 16 >> 8;
|
patch.rpnExpression.push_back(16 >> 8);
|
||||||
patch.rpnExpression[patch.rpnSize + 3] = 16 >> 16;
|
patch.rpnExpression.push_back(16 >> 16);
|
||||||
patch.rpnExpression[patch.rpnSize + 4] = 16 >> 24;
|
patch.rpnExpression.push_back(16 >> 24);
|
||||||
patch.rpnExpression[patch.rpnSize + 5] = (flags & 1 << RELOC_SIGNED) ? RPN_SHR : RPN_USHR;
|
patch.rpnExpression.push_back((flags & 1 << RELOC_SIGNED) ? RPN_SHR : RPN_USHR);
|
||||||
patch.rpnSize += 5 + 1;
|
|
||||||
} else {
|
} else {
|
||||||
if (flags & 1 << RELOC_EXPR16 && flags & 1 << RELOC_WHICHBYTE) {
|
if (flags & 1 << RELOC_EXPR16 && flags & 1 << RELOC_WHICHBYTE) {
|
||||||
patch.rpnExpression[patch.rpnSize] = RPN_CONST;
|
patch.rpnExpression.push_back(RPN_CONST);
|
||||||
patch.rpnExpression[patch.rpnSize + 1] = 8;
|
patch.rpnExpression.push_back(8);
|
||||||
patch.rpnExpression[patch.rpnSize + 2] = 8 >> 8;
|
patch.rpnExpression.push_back(8 >> 8);
|
||||||
patch.rpnExpression[patch.rpnSize + 3] = 8 >> 16;
|
patch.rpnExpression.push_back(8 >> 16);
|
||||||
patch.rpnExpression[patch.rpnSize + 4] = 8 >> 24;
|
patch.rpnExpression.push_back(8 >> 24);
|
||||||
patch.rpnExpression[patch.rpnSize + 5] = (flags & 1 << RELOC_SIGNED) ? RPN_SHR : RPN_USHR;
|
patch.rpnExpression.push_back((flags & 1 << RELOC_SIGNED) ? RPN_SHR : RPN_USHR);
|
||||||
patch.rpnSize += 5 + 1;
|
|
||||||
}
|
}
|
||||||
patch.rpnExpression[patch.rpnSize] = RPN_CONST;
|
patch.rpnExpression.push_back(RPN_CONST);
|
||||||
patch.rpnExpression[patch.rpnSize + 1] = 0xFF;
|
patch.rpnExpression.push_back(0xFF);
|
||||||
patch.rpnExpression[patch.rpnSize + 2] = 0xFF >> 8;
|
patch.rpnExpression.push_back(0xFF >> 8);
|
||||||
patch.rpnExpression[patch.rpnSize + 3] = 0xFF >> 16;
|
patch.rpnExpression.push_back(0xFF >> 16);
|
||||||
patch.rpnExpression[patch.rpnSize + 4] = 0xFF >> 24;
|
patch.rpnExpression.push_back(0xFF >> 24);
|
||||||
patch.rpnExpression[patch.rpnSize + 5] = RPN_AND;
|
patch.rpnExpression.push_back(RPN_AND);
|
||||||
patch.rpnSize += 5 + 1;
|
|
||||||
}
|
}
|
||||||
} else if (flags & 1 << RELOC_ISPCREL) {
|
} else if (flags & 1 << RELOC_ISPCREL) {
|
||||||
assert(patch.type == PATCHTYPE_WORD);
|
assert(patch.type == PATCHTYPE_WORD);
|
||||||
|
|||||||
Reference in New Issue
Block a user