shithub: rgbds

Download patch

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;
 }