From 2e9c68f8c37e8188bee63e7d164ee59ca6bc5d52 Mon Sep 17 00:00:00 2001 From: Sanqui Date: Mon, 28 Mar 2016 01:02:05 +0200 Subject: [PATCH] Add overlay file option to rgblink (-O) This option takes a file and places fixed sections on top of it. Should prove useful for patches and partial disassemblies. --- include/link/mylink.h | 1 + include/link/output.h | 1 + src/link/assign.c | 13 +++++++++ src/link/main.c | 10 ++++--- src/link/output.c | 61 ++++++++++++++++++++++++++++++++++++------- 5 files changed, 74 insertions(+), 12 deletions(-) diff --git a/include/link/mylink.h b/include/link/mylink.h index 707d5fbf..f9f003c9 100644 --- a/include/link/mylink.h +++ b/include/link/mylink.h @@ -10,6 +10,7 @@ extern SLONG options; #define OPT_SMALL 0x01 #define OPT_SMART_C_LINK 0x02 +#define OPT_OVERLAY 0x04 enum eRpnData { RPN_ADD = 0, diff --git a/include/link/output.h b/include/link/output.h index 7256a92c..06147cff 100644 --- a/include/link/output.h +++ b/include/link/output.h @@ -2,6 +2,7 @@ #define RGBDS_LINK_OUTPUT_H void out_Setname(char *tzOutputfile); +void out_SetOverlayname(char *tzOverlayfile); void Output(void); #endif diff --git a/src/link/assign.c b/src/link/assign.c index 1d4c1b2e..c5bd0961 100644 --- a/src/link/assign.c +++ b/src/link/assign.c @@ -713,6 +713,10 @@ AssignSections(void) && pSection->Type == SECT_ROMX && pSection->nOrg == -1 && pSection->nBank != -1) { /* User wants to have a say... and he's pissed */ + if (options & OPT_OVERLAY) { + errx(1, "All ROM sections must be fixed when using overlay"); + } + if (pSection->nBank >= 1 && pSection->nBank <= 511) { if ((pSection->nOrg = area_Alloc(&BankFree[pSection->nBank], @@ -789,6 +793,9 @@ AssignSections(void) && pSection->nOrg != -1 && pSection->nBank == -1) { /* User wants to have a say... and he's back with a * vengeance */ + if (options & OPT_OVERLAY) { + errx(1, "All ROM sections must be fixed when using overlay"); + } if ((pSection->nBank = area_AllocAbsROMXAnyBank(pSection->nOrg, pSection->nByteSize)) == @@ -875,6 +882,9 @@ AssignSections(void) case SECT_WRAMX: break; case SECT_ROM0: + if (options & OPT_OVERLAY) { + errx(1, "All ROM sections must be fixed when using overlay"); + } if ((pSection->nOrg = area_Alloc(&BankFree[BANK_ROM0], pSection->nByteSize)) == -1) { @@ -884,6 +894,9 @@ AssignSections(void) pSection->oAssigned = 1; break; case SECT_ROMX: + if (options & OPT_OVERLAY) { + errx(1, "All ROM sections must be fixed when using overlay"); + } break; default: errx(1, "(INTERNAL) Unknown section type!"); diff --git a/src/link/main.c b/src/link/main.c index 8eda44a8..ab87d9cb 100644 --- a/src/link/main.c +++ b/src/link/main.c @@ -35,8 +35,8 @@ static void usage(void) { printf( -"usage: rgblink [-t] [-m mapfile] [-n symfile] [-o outfile] [-p pad_value]\n" -" [-s symbol] file [...]\n"); +"usage: rgblink [-t] [-m mapfile] [-n symfile] [-O overlay] [-o outfile] \n" +" [-p pad_value] [-s symbol] file [...]\n"); exit(1); } @@ -56,7 +56,7 @@ main(int argc, char *argv[]) progname = argv[0]; - while ((ch = getopt(argc, argv, "m:n:o:p:s:t")) != -1) { + while ((ch = getopt(argc, argv, "m:n:o:O:p:s:t")) != -1) { switch (ch) { case 'm': SetMapfileName(optarg); @@ -67,6 +67,10 @@ main(int argc, char *argv[]) case 'o': out_Setname(optarg); break; + case 'O': + out_SetOverlayname(optarg); + options |= OPT_OVERLAY; + break; case 'p': fillchar = strtoul(optarg, &ep, 0); if (optarg[0] == '\0' || *ep != '\0') { diff --git a/src/link/output.c b/src/link/output.c index 95feb6de..0dee1be3 100644 --- a/src/link/output.c +++ b/src/link/output.c @@ -8,9 +8,12 @@ #include "link/assign.h" char *tzOutname; +char *tzOverlayname = NULL; + +SLONG MaxOverlayBank; void -writehome(FILE * f) +writehome(FILE * f, FILE * f_overlay) { struct sSection *pSect; UBYTE *mem; @@ -18,15 +21,20 @@ writehome(FILE * f) mem = malloc(MaxAvail[BANK_ROM0]); if (!mem) return; - - memset(mem, fillchar, MaxAvail[BANK_ROM0]); + + if (f_overlay != NULL) { + fseek(f_overlay, 0L, SEEK_SET); + fread(mem, 1, MaxAvail[BANK_ROM0], f_overlay); + } else { + memset(mem, fillchar, MaxAvail[BANK_ROM0]); + } MapfileInitBank(0); pSect = pSections; while (pSect) { if (pSect->Type == SECT_ROM0) { memcpy(mem + pSect->nOrg, pSect->pData, - pSect->nByteSize); + pSect->nByteSize); MapfileWriteSection(pSect); } pSect = pSect->pNext; @@ -39,7 +47,7 @@ writehome(FILE * f) } void -writebank(FILE * f, SLONG bank) +writebank(FILE * f, FILE * f_overlay, SLONG bank) { struct sSection *pSect; UBYTE *mem; @@ -48,14 +56,19 @@ writebank(FILE * f, SLONG bank) if (!mem) return; - memset(mem, fillchar, MaxAvail[bank]); + if (f_overlay != NULL && bank <= MaxOverlayBank) { + fseek(f_overlay, bank*0x4000, SEEK_SET); + fread(mem, 1, MaxAvail[bank], f_overlay); + } else { + memset(mem, fillchar, MaxAvail[bank]); + } MapfileInitBank(bank); pSect = pSections; while (pSect) { if (pSect->Type == SECT_ROMX && pSect->nBank == bank) { memcpy(mem + pSect->nOrg - 0x4000, pSect->pData, - pSect->nByteSize); + pSect->nByteSize); MapfileWriteSection(pSect); } pSect = pSect->pNext; @@ -73,18 +86,48 @@ out_Setname(char *tzOutputfile) tzOutname = tzOutputfile; } +void +out_SetOverlayname(char *tzOverlayfile) +{ + tzOverlayname = tzOverlayfile; +} + + void Output(void) { SLONG i; FILE *f; + FILE *f_overlay = NULL; + if ((f = fopen(tzOutname, "wb"))) { - writehome(f); + if (tzOverlayname) { + f_overlay = fopen(tzOverlayname, "rb"); + fseek(f_overlay, 0, SEEK_END); + if (ftell(f_overlay) % 0x4000 != 0) { + fprintf(stderr, "Overlay file must be aligned to 0x4000 bytes"); + exit(1); + } + MaxOverlayBank = (ftell(f_overlay) / 0x4000) - 1; + if (MaxOverlayBank < 1) { + fprintf(stderr, "Overlay file be at least 0x8000 bytes"); + exit(1); + } + if (MaxOverlayBank > MaxBankUsed) { + MaxBankUsed = MaxOverlayBank; + } + } + + writehome(f, f_overlay); for (i = 1; i <= MaxBankUsed; i += 1) - writebank(f, i); + writebank(f, f_overlay, i); fclose(f); + + if (tzOverlayname) { + fclose(f_overlay); + } } for (i = BANK_WRAM0; i < MAXBANKS; i++) { struct sSection *pSect;