ref: b1adbcc77c5ca8f5fbc8d52150979777560565ba
parent: dda052da201834b4604c3cb329f423d244505592
author: ISSOtm <[email protected]>
date: Mon Jul 27 13:32:47 EDT 2020
Output a non-empty RPN buffer from known expressions The code expected to never get "known" expressions passed in, as RGBASM otherwise patches the bytes in by itself; however, JR cannot be patched in by RGBASM unless the section's base address is known as well!
--- a/src/asm/output.c
+++ b/src/asm/output.c
@@ -308,16 +308,16 @@
uint32_t ofs)
{
struct Patch *pPatch = malloc(sizeof(struct Patch));
+ uint32_t rpnSize = expr->isKnown ? 5 : expr->nRPNPatchSize;
if (!pPatch)
fatalerror("No memory for patch: %s", strerror(errno));
- pPatch->pRPN = malloc(sizeof(*pPatch->pRPN) * expr->nRPNPatchSize);
+ pPatch->pRPN = malloc(sizeof(*pPatch->pRPN) * rpnSize);
if (!pPatch->pRPN)
fatalerror("No memory for patch's RPN expression: %s",
strerror(errno));
- pPatch->nRPNSize = 0;
pPatch->nType = type;
fstk_DumpToStr(pPatch->tzFilename, sizeof(pPatch->tzFilename));
pPatch->nOffset = ofs;
@@ -324,8 +324,20 @@
pPatch->pcSection = sect_GetSymbolSection();
pPatch->pcOffset = curOffset;
- writerpn(pPatch->pRPN, &pPatch->nRPNSize, expr->tRPN, expr->nRPNLength);
- assert(pPatch->nRPNSize == expr->nRPNPatchSize);
+ /* If the expression's value is known, output a constant RPN expression directly */
+ if (expr->isKnown) {
+ pPatch->nRPNSize = rpnSize;
+ /* Make sure to update `rpnSize` above if modifying this! */
+ pPatch->pRPN[0] = RPN_CONST;
+ pPatch->pRPN[1] = (uint32_t)(expr->nVal) & 0xFF;
+ pPatch->pRPN[2] = (uint32_t)(expr->nVal) >> 8;
+ pPatch->pRPN[3] = (uint32_t)(expr->nVal) >> 16;
+ pPatch->pRPN[4] = (uint32_t)(expr->nVal) >> 24;
+ } else {
+ pPatch->nRPNSize = 0;
+ writerpn(pPatch->pRPN, &pPatch->nRPNSize, expr->tRPN, expr->nRPNLength);
+ }
+ assert(pPatch->nRPNSize == rpnSize);
return pPatch;
}