mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
@@ -10,6 +10,7 @@
|
|||||||
extern SLONG options;
|
extern SLONG options;
|
||||||
#define OPT_SMALL 0x01
|
#define OPT_SMALL 0x01
|
||||||
#define OPT_SMART_C_LINK 0x02
|
#define OPT_SMART_C_LINK 0x02
|
||||||
|
#define OPT_OVERLAY 0x04
|
||||||
|
|
||||||
enum eRpnData {
|
enum eRpnData {
|
||||||
RPN_ADD = 0,
|
RPN_ADD = 0,
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
#define RGBDS_LINK_OUTPUT_H
|
#define RGBDS_LINK_OUTPUT_H
|
||||||
|
|
||||||
void out_Setname(char *tzOutputfile);
|
void out_Setname(char *tzOutputfile);
|
||||||
|
void out_SetOverlayname(char *tzOverlayfile);
|
||||||
void Output(void);
|
void Output(void);
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|||||||
@@ -265,6 +265,9 @@ AssignFloatingBankSections(enum eSectionType type)
|
|||||||
SLONG org;
|
SLONG org;
|
||||||
|
|
||||||
if ((org = area_AllocAnyBank(pSection->nByteSize, pSection->nAlign, type)) != -1) {
|
if ((org = area_AllocAnyBank(pSection->nByteSize, pSection->nAlign, type)) != -1) {
|
||||||
|
if (options & OPT_OVERLAY) {
|
||||||
|
errx(1, "All sections must be fixed when using overlay");
|
||||||
|
}
|
||||||
pSection->nOrg = org & 0xFFFF;
|
pSection->nOrg = org & 0xFFFF;
|
||||||
pSection->nBank = org >> 16;
|
pSection->nBank = org >> 16;
|
||||||
pSection->oAssigned = 1;
|
pSection->oAssigned = 1;
|
||||||
@@ -421,6 +424,9 @@ AssignSections(void)
|
|||||||
while (pSection) {
|
while (pSection) {
|
||||||
if (pSection->oAssigned == 0
|
if (pSection->oAssigned == 0
|
||||||
&& pSection->nOrg != -1 && pSection->nBank == -1) {
|
&& pSection->nOrg != -1 && pSection->nBank == -1) {
|
||||||
|
if (options & OPT_OVERLAY) {
|
||||||
|
errx(1, "All sections must be fixed when using overlay");
|
||||||
|
}
|
||||||
switch (pSection->Type) {
|
switch (pSection->Type) {
|
||||||
case SECT_ROMX:
|
case SECT_ROMX:
|
||||||
case SECT_VRAM:
|
case SECT_VRAM:
|
||||||
|
|||||||
@@ -35,8 +35,8 @@ static void
|
|||||||
usage(void)
|
usage(void)
|
||||||
{
|
{
|
||||||
printf(
|
printf(
|
||||||
"usage: rgblink [-t] [-m mapfile] [-n symfile] [-o outfile] [-p pad_value]\n"
|
"usage: rgblink [-t] [-m mapfile] [-n symfile] [-O overlay] [-o outfile] \n"
|
||||||
" [-s symbol] file [...]\n");
|
" [-p pad_value] [-s symbol] file [...]\n");
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +56,7 @@ main(int argc, char *argv[])
|
|||||||
|
|
||||||
progname = argv[0];
|
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) {
|
switch (ch) {
|
||||||
case 'm':
|
case 'm':
|
||||||
SetMapfileName(optarg);
|
SetMapfileName(optarg);
|
||||||
@@ -67,6 +67,10 @@ main(int argc, char *argv[])
|
|||||||
case 'o':
|
case 'o':
|
||||||
out_Setname(optarg);
|
out_Setname(optarg);
|
||||||
break;
|
break;
|
||||||
|
case 'O':
|
||||||
|
out_SetOverlayname(optarg);
|
||||||
|
options |= OPT_OVERLAY;
|
||||||
|
break;
|
||||||
case 'p':
|
case 'p':
|
||||||
fillchar = strtoul(optarg, &ep, 0);
|
fillchar = strtoul(optarg, &ep, 0);
|
||||||
if (optarg[0] == '\0' || *ep != '\0') {
|
if (optarg[0] == '\0' || *ep != '\0') {
|
||||||
|
|||||||
@@ -8,9 +8,12 @@
|
|||||||
#include "link/assign.h"
|
#include "link/assign.h"
|
||||||
|
|
||||||
char *tzOutname;
|
char *tzOutname;
|
||||||
|
char *tzOverlayname = NULL;
|
||||||
|
|
||||||
|
SLONG MaxOverlayBank;
|
||||||
|
|
||||||
void
|
void
|
||||||
writehome(FILE * f)
|
writehome(FILE * f, FILE * f_overlay)
|
||||||
{
|
{
|
||||||
struct sSection *pSect;
|
struct sSection *pSect;
|
||||||
UBYTE *mem;
|
UBYTE *mem;
|
||||||
@@ -19,7 +22,12 @@ writehome(FILE * f)
|
|||||||
if (!mem)
|
if (!mem)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
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]);
|
memset(mem, fillchar, MaxAvail[BANK_ROM0]);
|
||||||
|
}
|
||||||
MapfileInitBank(0);
|
MapfileInitBank(0);
|
||||||
|
|
||||||
pSect = pSections;
|
pSect = pSections;
|
||||||
@@ -39,7 +47,7 @@ writehome(FILE * f)
|
|||||||
}
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
writebank(FILE * f, SLONG bank)
|
writebank(FILE * f, FILE * f_overlay, SLONG bank)
|
||||||
{
|
{
|
||||||
struct sSection *pSect;
|
struct sSection *pSect;
|
||||||
UBYTE *mem;
|
UBYTE *mem;
|
||||||
@@ -48,7 +56,12 @@ writebank(FILE * f, SLONG bank)
|
|||||||
if (!mem)
|
if (!mem)
|
||||||
return;
|
return;
|
||||||
|
|
||||||
|
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]);
|
memset(mem, fillchar, MaxAvail[bank]);
|
||||||
|
}
|
||||||
MapfileInitBank(bank);
|
MapfileInitBank(bank);
|
||||||
|
|
||||||
pSect = pSections;
|
pSect = pSections;
|
||||||
@@ -73,18 +86,52 @@ out_Setname(char *tzOutputfile)
|
|||||||
tzOutname = tzOutputfile;
|
tzOutname = tzOutputfile;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void
|
||||||
|
out_SetOverlayname(char *tzOverlayfile)
|
||||||
|
{
|
||||||
|
tzOverlayname = tzOverlayfile;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
void
|
void
|
||||||
Output(void)
|
Output(void)
|
||||||
{
|
{
|
||||||
SLONG i;
|
SLONG i;
|
||||||
FILE *f;
|
FILE *f;
|
||||||
|
FILE *f_overlay = NULL;
|
||||||
|
|
||||||
|
|
||||||
if ((f = fopen(tzOutname, "wb"))) {
|
if ((f = fopen(tzOutname, "wb"))) {
|
||||||
writehome(f);
|
if (tzOverlayname) {
|
||||||
|
f_overlay = fopen(tzOverlayname, "rb");
|
||||||
|
if (!f_overlay) {
|
||||||
|
fprintf(stderr, "Failed to open overlay file %s\n", tzOverlayname);
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
fseek(f_overlay, 0, SEEK_END);
|
||||||
|
if (ftell(f_overlay) % 0x4000 != 0) {
|
||||||
|
fprintf(stderr, "Overlay file must be aligned to 0x4000 bytes\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
MaxOverlayBank = (ftell(f_overlay) / 0x4000) - 1;
|
||||||
|
if (MaxOverlayBank < 1) {
|
||||||
|
fprintf(stderr, "Overlay file be at least 0x8000 bytes\n");
|
||||||
|
exit(1);
|
||||||
|
}
|
||||||
|
if (MaxOverlayBank > MaxBankUsed) {
|
||||||
|
MaxBankUsed = MaxOverlayBank;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
writehome(f, f_overlay);
|
||||||
for (i = 1; i <= MaxBankUsed; i += 1)
|
for (i = 1; i <= MaxBankUsed; i += 1)
|
||||||
writebank(f, i);
|
writebank(f, f_overlay, i);
|
||||||
|
|
||||||
fclose(f);
|
fclose(f);
|
||||||
|
|
||||||
|
if (tzOverlayname) {
|
||||||
|
fclose(f_overlay);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
for (i = BANK_WRAM0; i < MAXBANKS; i++) {
|
for (i = BANK_WRAM0; i < MAXBANKS; i++) {
|
||||||
struct sSection *pSect;
|
struct sSection *pSect;
|
||||||
|
|||||||
@@ -9,6 +9,7 @@
|
|||||||
.Op Fl t
|
.Op Fl t
|
||||||
.Op Fl m Ar mapfile
|
.Op Fl m Ar mapfile
|
||||||
.Op Fl n Ar symfile
|
.Op Fl n Ar symfile
|
||||||
|
.Op Fl O Ar overlayfile
|
||||||
.Op Fl o Ar outfile
|
.Op Fl o Ar outfile
|
||||||
.Op Fl p Ar pad_value
|
.Op Fl p Ar pad_value
|
||||||
.Op Fl s Ar symbol
|
.Op Fl s Ar symbol
|
||||||
@@ -32,6 +33,10 @@ The arguments are as follows:
|
|||||||
Write a mapfile to the given filename.
|
Write a mapfile to the given filename.
|
||||||
.It Fl n Ar symfile
|
.It Fl n Ar symfile
|
||||||
Write a symbol file to the given filename.
|
Write a symbol file to the given filename.
|
||||||
|
.It Fl O Ar overlayfile
|
||||||
|
The ROM image to overlay sections over.
|
||||||
|
When an overlay ROM is provided, all sections must be fixed.
|
||||||
|
This may be used to patch an existing binray.
|
||||||
.It Fl o Ar outfile
|
.It Fl o Ar outfile
|
||||||
Write ROM image to the given filename.
|
Write ROM image to the given filename.
|
||||||
.It Fl p Ar pad_value
|
.It Fl p Ar pad_value
|
||||||
|
|||||||
Reference in New Issue
Block a user