mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Cleanup code of rbglink
Follow Linux kernel coding style. Signed-off-by: Antonio Niño Díaz <antonio_nd@outlook.com>
This commit is contained in:
@@ -27,8 +27,10 @@ enum eBankDefine {
|
||||
BANK_SRAM = BANK_HRAM + BANK_COUNT_HRAM
|
||||
};
|
||||
|
||||
#define MAXBANKS (BANK_COUNT_ROM0 + BANK_COUNT_ROMX + BANK_COUNT_WRAM0 + BANK_COUNT_WRAMX \
|
||||
+ BANK_COUNT_VRAM + BANK_COUNT_OAM + BANK_COUNT_HRAM + BANK_COUNT_SRAM)
|
||||
#define MAXBANKS (BANK_COUNT_ROM0 + BANK_COUNT_ROMX \
|
||||
+ BANK_COUNT_WRAM0 + BANK_COUNT_WRAMX \
|
||||
+ BANK_COUNT_VRAM + BANK_COUNT_OAM \
|
||||
+ BANK_COUNT_HRAM + BANK_COUNT_SRAM)
|
||||
|
||||
extern int32_t MaxBankUsed;
|
||||
extern int32_t MaxAvail[MAXBANKS];
|
||||
@@ -36,17 +38,11 @@ extern int32_t MaxAvail[MAXBANKS];
|
||||
int32_t area_Avail(int32_t bank);
|
||||
void AssignSections(void);
|
||||
void CreateSymbolTable(void);
|
||||
int32_t IsSectionNameInUse(const char *name);
|
||||
void SetLinkerscriptName(char *tzLinkerscriptFile);
|
||||
int32_t IsSectionSameTypeBankAndFloating(const char *name,
|
||||
enum eSectionType type, int32_t bank);
|
||||
uint32_t AssignSectionAddressAndBankByName(const char *name, uint32_t address,
|
||||
int32_t bank);
|
||||
|
||||
int32_t
|
||||
IsSectionNameInUse(const char *name);
|
||||
|
||||
void
|
||||
SetLinkerscriptName(char *tzLinkerscriptFile);
|
||||
|
||||
int32_t
|
||||
IsSectionSameTypeBankAndFloating(const char *name, enum eSectionType type, int32_t bank);
|
||||
|
||||
uint32_t
|
||||
AssignSectionAddressAndBankByName(const char *name, uint32_t address, int32_t bank);
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_LINK_ASSIGN_H */
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
void AddNeededModules(void);
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_LINK_LIBRARY_H */
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
extern int32_t fillchar;
|
||||
extern char *smartlinkstartsymbol;
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_LINK_MAIN_H */
|
||||
|
||||
@@ -6,8 +6,8 @@
|
||||
void SetMapfileName(char *name);
|
||||
void SetSymfileName(char *name);
|
||||
void CloseMapfile(void);
|
||||
void MapfileWriteSection(struct sSection * pSect);
|
||||
void MapfileWriteSection(const struct sSection *pSect);
|
||||
void MapfileInitBank(int32_t bank);
|
||||
void MapfileCloseBank(int32_t slack);
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_LINK_MAPFILE_H */
|
||||
|
||||
@@ -82,10 +82,12 @@ enum eSymbolType {
|
||||
struct sSymbol {
|
||||
char *pzName;
|
||||
enum eSymbolType Type;
|
||||
/* the following 3 items only valid when Type!=SYM_IMPORT */
|
||||
int32_t nSectionID; /* internal to object.c */
|
||||
|
||||
/* The following 3 items only valid when Type!=SYM_IMPORT */
|
||||
int32_t nSectionID; /* Internal to object.c */
|
||||
struct sSection *pSection;
|
||||
int32_t nOffset;
|
||||
|
||||
char *pzObjFileName; /* Object file where the symbol is located. */
|
||||
char *pzFileName; /* Source file where the symbol was defined. */
|
||||
uint32_t nFileLine; /* Line where the symbol was defined. */
|
||||
@@ -111,4 +113,4 @@ struct sPatch {
|
||||
extern struct sSection *pSections;
|
||||
extern struct sSection *pLibSections;
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_LINK_LINK_H */
|
||||
|
||||
@@ -3,4 +3,4 @@
|
||||
|
||||
void obj_Readfile(char *tzObjectfile);
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_LINK_OBJECT_H */
|
||||
|
||||
@@ -5,4 +5,4 @@ void out_Setname(char *tzOutputfile);
|
||||
void out_SetOverlayname(char *tzOverlayfile);
|
||||
void Output(void);
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_LINK_OUTPUT_H */
|
||||
|
||||
@@ -6,4 +6,4 @@
|
||||
void Patch(void);
|
||||
extern int32_t nPC;
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_LINK_PATCH_H */
|
||||
|
||||
@@ -35,5 +35,4 @@ void script_SetAddress(uint32_t addr);
|
||||
void script_SetAlignment(uint32_t alignment);
|
||||
void script_OutputSection(const char *section_name);
|
||||
|
||||
#endif
|
||||
|
||||
#endif /* RGBDS_LINK_SCRIPT_H */
|
||||
|
||||
@@ -5,8 +5,9 @@
|
||||
|
||||
void sym_Init(void);
|
||||
void sym_CreateSymbol(char *tzName, int32_t nValue, int32_t nBank,
|
||||
char *tzObjFileName, char *tzFileName, uint32_t nFileLine);
|
||||
char *tzObjFileName, char *tzFileName,
|
||||
uint32_t nFileLine);
|
||||
int32_t sym_GetValue(char *tzName);
|
||||
int32_t sym_GetBank(char *tzName);
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_LINK_SYMBOL_H */
|
||||
|
||||
@@ -5,4 +5,4 @@
|
||||
#define _MAX_PATH 512
|
||||
#endif
|
||||
|
||||
#endif
|
||||
#endif /* RGBDS_TYPES_H */
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "extern/err.h"
|
||||
|
||||
#include "link/assign.h"
|
||||
#include "link/mylink.h"
|
||||
#include "link/main.h"
|
||||
@@ -19,8 +20,9 @@ struct sFreeArea {
|
||||
|
||||
struct sSectionAttributes {
|
||||
const char *name;
|
||||
/* bank + offset = bank originally stored in a section struct */
|
||||
int32_t bank;
|
||||
int32_t offset; // bank + offset = bank originally stored in a section struct
|
||||
int32_t offset;
|
||||
int32_t minBank;
|
||||
int32_t bankCount;
|
||||
};
|
||||
@@ -45,27 +47,37 @@ const struct sSectionAttributes SECT_ATTRIBUTES[] = {
|
||||
{"OAM", BANK_OAM, 0, 0, BANK_COUNT_OAM}
|
||||
};
|
||||
|
||||
#define DOMAXBANK(x, y) {switch (x) { \
|
||||
case SECT_ROMX: DOMAXRBANK(y); break; \
|
||||
case SECT_WRAMX: DOMAXWBANK(y); break; \
|
||||
case SECT_SRAM: DOMAXSBANK(y); break; \
|
||||
case SECT_VRAM: DOMAXVBANK(y); break; \
|
||||
default: break; }}
|
||||
#define DOMAXRBANK(x) {if( (x)>MaxBankUsed ) MaxBankUsed=(x);}
|
||||
#define DOMAXWBANK(x) {if( (x)>MaxWBankUsed ) MaxWBankUsed=(x);}
|
||||
#define DOMAXSBANK(x) {if( (x)>MaxSBankUsed ) MaxSBankUsed=(x);}
|
||||
#define DOMAXVBANK(x) {if( (x)>MaxVBankUsed ) MaxVBankUsed=(x);}
|
||||
|
||||
void
|
||||
ensureSectionTypeIsValid(enum eSectionType type)
|
||||
static void do_max_bank(enum eSectionType Type, int32_t nBank)
|
||||
{
|
||||
if (type < SECT_MIN || type > SECT_MAX) {
|
||||
errx(1, "(INTERNAL) Invalid section type found.");
|
||||
switch (Type) {
|
||||
case SECT_ROMX:
|
||||
if (nBank > MaxBankUsed)
|
||||
MaxBankUsed = nBank;
|
||||
break;
|
||||
case SECT_WRAMX:
|
||||
if (nBank > MaxWBankUsed)
|
||||
MaxWBankUsed = nBank;
|
||||
break;
|
||||
case SECT_SRAM:
|
||||
if (nBank > MaxSBankUsed)
|
||||
MaxSBankUsed = nBank;
|
||||
break;
|
||||
case SECT_VRAM:
|
||||
if (nBank > MaxVBankUsed)
|
||||
MaxVBankUsed = nBank;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
int32_t
|
||||
area_Avail(int32_t bank)
|
||||
void ensureSectionTypeIsValid(enum eSectionType type)
|
||||
{
|
||||
if (type < SECT_MIN || type > SECT_MAX)
|
||||
errx(1, "(INTERNAL) Invalid section type found.");
|
||||
}
|
||||
|
||||
int32_t area_Avail(int32_t bank)
|
||||
{
|
||||
int32_t r;
|
||||
struct sFreeArea *pArea;
|
||||
@@ -78,54 +90,55 @@ area_Avail(int32_t bank)
|
||||
pArea = pArea->pNext;
|
||||
}
|
||||
|
||||
return (r);
|
||||
return r;
|
||||
}
|
||||
|
||||
int32_t
|
||||
area_doAlloc(struct sFreeArea *pArea, int32_t org, int32_t size)
|
||||
int32_t area_doAlloc(struct sFreeArea *pArea, int32_t org, int32_t size)
|
||||
{
|
||||
if (org >= pArea->nOrg && (org + size) <= (pArea->nOrg + pArea->nSize)) {
|
||||
if ((org >= pArea->nOrg)
|
||||
&& ((org + size) <= (pArea->nOrg + pArea->nSize))) {
|
||||
|
||||
if (org == pArea->nOrg) {
|
||||
pArea->nOrg += size;
|
||||
pArea->nSize -= size;
|
||||
return org;
|
||||
} else {
|
||||
if ((org + size) == (pArea->nOrg + pArea->nSize)) {
|
||||
pArea->nSize -= size;
|
||||
return org;
|
||||
} else {
|
||||
struct sFreeArea *pNewArea;
|
||||
|
||||
if ((pNewArea = malloc(sizeof(struct sFreeArea))) != NULL) {
|
||||
*pNewArea = *pArea;
|
||||
pNewArea->pPrev = pArea;
|
||||
pArea->pNext = pNewArea;
|
||||
pArea->nSize = org - pArea->nOrg;
|
||||
pNewArea->nOrg = org + size;
|
||||
pNewArea->nSize -= size + pArea->nSize;
|
||||
return org;
|
||||
|
||||
} else {
|
||||
err(1, NULL);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ((org + size) == (pArea->nOrg + pArea->nSize)) {
|
||||
pArea->nSize -= size;
|
||||
return org;
|
||||
}
|
||||
|
||||
struct sFreeArea *pNewArea;
|
||||
|
||||
pNewArea = malloc(sizeof(struct sFreeArea));
|
||||
|
||||
if (pNewArea == NULL)
|
||||
err(1, NULL);
|
||||
|
||||
*pNewArea = *pArea;
|
||||
pNewArea->pPrev = pArea;
|
||||
pArea->pNext = pNewArea;
|
||||
pArea->nSize = org - pArea->nOrg;
|
||||
pNewArea->nOrg = org + size;
|
||||
pNewArea->nSize -= size + pArea->nSize;
|
||||
|
||||
return org;
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t
|
||||
area_AllocAbs(struct sFreeArea ** ppArea, int32_t org, int32_t size)
|
||||
int32_t area_AllocAbs(struct sFreeArea **ppArea, int32_t org, int32_t size)
|
||||
{
|
||||
struct sFreeArea *pArea;
|
||||
|
||||
pArea = *ppArea;
|
||||
while (pArea) {
|
||||
int32_t result = area_doAlloc(pArea, org, size);
|
||||
if (result != -1) {
|
||||
|
||||
if (result != -1)
|
||||
return result;
|
||||
}
|
||||
|
||||
ppArea = &(pArea->pNext);
|
||||
pArea = *ppArea;
|
||||
@@ -134,8 +147,7 @@ area_AllocAbs(struct sFreeArea ** ppArea, int32_t org, int32_t size)
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t
|
||||
area_AllocAbsAnyBank(int32_t org, int32_t size, enum eSectionType type)
|
||||
int32_t area_AllocAbsAnyBank(int32_t org, int32_t size, enum eSectionType type)
|
||||
{
|
||||
ensureSectionTypeIsValid(type);
|
||||
|
||||
@@ -143,33 +155,33 @@ area_AllocAbsAnyBank(int32_t org, int32_t size, enum eSectionType type)
|
||||
int32_t bankCount = SECT_ATTRIBUTES[type].bankCount;
|
||||
|
||||
for (int32_t i = 0; i < bankCount; i++) {
|
||||
if (area_AllocAbs(&BankFree[startBank + i], org, size) != -1) {
|
||||
if (area_AllocAbs(&BankFree[startBank + i], org, size) != -1)
|
||||
return startBank + i;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t
|
||||
area_Alloc(struct sFreeArea ** ppArea, int32_t size, int32_t alignment) {
|
||||
int32_t area_Alloc(struct sFreeArea **ppArea, int32_t size, int32_t alignment)
|
||||
{
|
||||
struct sFreeArea *pArea;
|
||||
if (alignment < 1) {
|
||||
|
||||
if (alignment < 1)
|
||||
alignment = 1;
|
||||
}
|
||||
|
||||
pArea = *ppArea;
|
||||
while (pArea) {
|
||||
int32_t org = pArea->nOrg;
|
||||
if (org % alignment) {
|
||||
|
||||
if (org % alignment)
|
||||
org += alignment;
|
||||
}
|
||||
|
||||
org -= org % alignment;
|
||||
|
||||
int32_t result = area_doAlloc(pArea, org, size);
|
||||
if (result != -1) {
|
||||
|
||||
if (result != -1)
|
||||
return result;
|
||||
}
|
||||
|
||||
ppArea = &(pArea->pNext);
|
||||
pArea = *ppArea;
|
||||
@@ -178,25 +190,25 @@ area_Alloc(struct sFreeArea ** ppArea, int32_t size, int32_t alignment) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
int32_t
|
||||
area_AllocAnyBank(int32_t size, int32_t alignment, enum eSectionType type) {
|
||||
int32_t area_AllocAnyBank(int32_t size, int32_t alignment,
|
||||
enum eSectionType type)
|
||||
{
|
||||
ensureSectionTypeIsValid(type);
|
||||
|
||||
int32_t i, org;
|
||||
int32_t startBank = SECT_ATTRIBUTES[type].bank;
|
||||
int32_t bankCount = SECT_ATTRIBUTES[type].bankCount;
|
||||
|
||||
for (int32_t i = 0; i < bankCount; i++) {
|
||||
int32_t org = area_Alloc(&BankFree[startBank + i], size, alignment);
|
||||
if (org != -1) {
|
||||
for (i = 0; i < bankCount; i++) {
|
||||
org = area_Alloc(&BankFree[startBank + i], size, alignment);
|
||||
if (org != -1)
|
||||
return ((startBank + i) << 16) | org;
|
||||
}
|
||||
}
|
||||
|
||||
return -1;
|
||||
}
|
||||
|
||||
struct sSection *
|
||||
FindLargestSection(enum eSectionType type, bool bankFixed)
|
||||
struct sSection *FindLargestSection(enum eSectionType type, bool bankFixed)
|
||||
{
|
||||
struct sSection *pSection, *r = NULL;
|
||||
int32_t nLargest = 0;
|
||||
@@ -204,8 +216,12 @@ FindLargestSection(enum eSectionType type, bool bankFixed)
|
||||
|
||||
pSection = pSections;
|
||||
while (pSection) {
|
||||
if (pSection->oAssigned == 0 && pSection->Type == type && (bankFixed ^ (pSection->nBank == -1))) {
|
||||
if (pSection->nAlign > nLargestAlignment || (pSection->nAlign == nLargestAlignment && pSection->nByteSize > nLargest)) {
|
||||
if (pSection->oAssigned == 0 && pSection->Type == type
|
||||
&& (bankFixed ^ (pSection->nBank == -1))) {
|
||||
if (pSection->nAlign > nLargestAlignment
|
||||
|| (pSection->nAlign == nLargestAlignment
|
||||
&& pSection->nByteSize > nLargest)) {
|
||||
|
||||
nLargest = pSection->nByteSize;
|
||||
nLargestAlignment = pSection->nAlign;
|
||||
r = pSection;
|
||||
@@ -217,12 +233,10 @@ FindLargestSection(enum eSectionType type, bool bankFixed)
|
||||
return r;
|
||||
}
|
||||
|
||||
int32_t
|
||||
IsSectionNameInUse(const char *name)
|
||||
int32_t IsSectionNameInUse(const char *name)
|
||||
{
|
||||
struct sSection *pSection;
|
||||
const struct sSection *pSection = pSections;
|
||||
|
||||
pSection = pSections;
|
||||
while (pSection) {
|
||||
if (strcmp(pSection->pzName, name) == 0)
|
||||
return 1;
|
||||
@@ -233,100 +247,135 @@ IsSectionNameInUse(const char *name)
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
int32_t
|
||||
IsSectionSameTypeBankAndFloating(const char *name, enum eSectionType type, int32_t bank)
|
||||
int32_t IsSectionSameTypeBankAndFloating(const char *name,
|
||||
enum eSectionType type, int32_t bank)
|
||||
{
|
||||
struct sSection *pSection;
|
||||
const struct sSection *pSection;
|
||||
|
||||
pSection = pSections;
|
||||
while (pSection) {
|
||||
if (pSection->oAssigned == 0) {
|
||||
if (strcmp(pSection->pzName, name) == 0) {
|
||||
/* Section must be floating in source */
|
||||
if (pSection->nOrg != -1 || pSection->nAlign != 1)
|
||||
return 0;
|
||||
/* It must have the same type in source and linkerscript */
|
||||
if (pSection->Type != type)
|
||||
return 0;
|
||||
/* Bank number must be unassigned in source or equal */
|
||||
if (pSection->nBank != -1 && pSection->nBank != bank)
|
||||
return 0;
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
pSection = pSection->pNext;
|
||||
for (pSection = pSections; pSection; pSection = pSection->pNext) {
|
||||
/* Skip if it has already been assigned */
|
||||
if (pSection->oAssigned == 1)
|
||||
continue;
|
||||
|
||||
/* Check if it has the same name */
|
||||
if (strcmp(pSection->pzName, name) != 0)
|
||||
continue;
|
||||
|
||||
/*
|
||||
* The section has the same name, now check if there is a
|
||||
* mismatch or not.
|
||||
*/
|
||||
|
||||
/* Section must be floating in source */
|
||||
if (pSection->nOrg != -1 || pSection->nAlign != 1)
|
||||
return 0;
|
||||
|
||||
/* It must have the same type in source and linkerscript */
|
||||
if (pSection->Type != type)
|
||||
return 0;
|
||||
|
||||
/* Bank number must be unassigned in source or equal */
|
||||
if (pSection->nBank != -1 && pSection->nBank != bank)
|
||||
return 0;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
errx(1, "Section \"%s\" not found (or already used).\n", name);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
AssignSectionAddressAndBankByName(const char *name, uint32_t address, int32_t bank)
|
||||
uint32_t AssignSectionAddressAndBankByName(const char *name, uint32_t address,
|
||||
int32_t bank)
|
||||
{
|
||||
struct sSection *pSection;
|
||||
|
||||
pSection = pSections;
|
||||
while (pSection) {
|
||||
if (pSection->oAssigned == 0) {
|
||||
if (strcmp(pSection->pzName, name) == 0) {
|
||||
if (pSection->nOrg != -1 || pSection->nAlign != 1)
|
||||
errx(1, "Section \"%s\" from linkerscript isn't floating.\n", name);
|
||||
if (pSection->nBank != -1 && pSection->nBank != bank)
|
||||
errx(1, "Section \"%s\" from linkerscript has different bank number than in the source.\n", name);
|
||||
pSection->nOrg = address;
|
||||
pSection->nBank = bank;
|
||||
pSection->nAlign = -1;
|
||||
return pSection->nByteSize;
|
||||
}
|
||||
for (pSection = pSections; pSection; pSection = pSection->pNext) {
|
||||
/* Skip if it has already been assigned */
|
||||
if (pSection->oAssigned == 1)
|
||||
continue;
|
||||
|
||||
/* Check if it has the same name */
|
||||
if (strcmp(pSection->pzName, name) != 0)
|
||||
continue;
|
||||
|
||||
/* Section has been found. */
|
||||
|
||||
/*
|
||||
* A section can be left as floating in the code if the location
|
||||
* is assigned in the linkerscript.
|
||||
*/
|
||||
if (pSection->nOrg != -1 || pSection->nAlign != 1) {
|
||||
errx(1, "Section \"%s\" from linkerscript isn't floating.\n",
|
||||
name);
|
||||
}
|
||||
pSection = pSection->pNext;
|
||||
|
||||
/* The bank can be left as unassigned or be the same */
|
||||
if (pSection->nBank != -1 && pSection->nBank != bank) {
|
||||
errx(1, "Section \"%s\" from linkerscript has different bank number than in the source.\n",
|
||||
name);
|
||||
}
|
||||
|
||||
pSection->nOrg = address;
|
||||
pSection->nBank = bank;
|
||||
pSection->nAlign = -1;
|
||||
|
||||
return pSection->nByteSize;
|
||||
}
|
||||
|
||||
errx(1, "Section \"%s\" not found (or already used).\n", name);
|
||||
}
|
||||
|
||||
bool
|
||||
VerifyAndSetBank(struct sSection *pSection)
|
||||
bool VerifyAndSetBank(struct sSection *pSection)
|
||||
{
|
||||
ensureSectionTypeIsValid(pSection->Type);
|
||||
enum eSectionType Type = pSection->Type;
|
||||
|
||||
if (pSection->nBank >= SECT_ATTRIBUTES[pSection->Type].minBank
|
||||
&& pSection->nBank < SECT_ATTRIBUTES[pSection->Type].minBank + SECT_ATTRIBUTES[pSection->Type].bankCount) {
|
||||
pSection->nBank += SECT_ATTRIBUTES[pSection->Type].bank + SECT_ATTRIBUTES[pSection->Type].offset;
|
||||
return true;
|
||||
ensureSectionTypeIsValid(Type);
|
||||
|
||||
} else {
|
||||
return false;
|
||||
if (pSection->nBank >= SECT_ATTRIBUTES[Type].minBank) {
|
||||
if (pSection->nBank < SECT_ATTRIBUTES[Type].minBank
|
||||
+ SECT_ATTRIBUTES[Type].bankCount) {
|
||||
pSection->nBank += SECT_ATTRIBUTES[Type].bank
|
||||
+ SECT_ATTRIBUTES[Type].offset;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
void
|
||||
AssignFixedBankSections(enum eSectionType type)
|
||||
void AssignFixedBankSections(enum eSectionType type)
|
||||
{
|
||||
ensureSectionTypeIsValid(type);
|
||||
|
||||
struct sSection *pSection;
|
||||
|
||||
while ((pSection = FindLargestSection(type, true))) {
|
||||
if (VerifyAndSetBank(pSection) &&
|
||||
(pSection->nOrg = area_Alloc(&BankFree[pSection->nBank], pSection->nByteSize, pSection->nAlign)) != -1) {
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXBANK(pSection->Type, pSection->nBank);
|
||||
} else {
|
||||
if (pSection->nAlign <= 1) {
|
||||
errx(1, "Unable to place '%s' (%s section) in bank $%02lX",
|
||||
pSection->pzName, SECT_ATTRIBUTES[pSection->Type].name, pSection->nBank);
|
||||
} else {
|
||||
errx(1, "Unable to place '%s' (%s section) in bank $%02lX (with $%lX-byte alignment)",
|
||||
pSection->pzName, SECT_ATTRIBUTES[pSection->Type].name, pSection->nBank, pSection->nAlign);
|
||||
if (VerifyAndSetBank(pSection)) {
|
||||
pSection->nOrg = area_Alloc(&BankFree[pSection->nBank],
|
||||
pSection->nByteSize,
|
||||
pSection->nAlign);
|
||||
if (pSection->nOrg != -1) {
|
||||
pSection->oAssigned = 1;
|
||||
do_max_bank(pSection->Type, pSection->nBank);
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (pSection->nAlign <= 1) {
|
||||
errx(1, "Unable to place '%s' (%s section) in bank $%02lX",
|
||||
pSection->pzName,
|
||||
SECT_ATTRIBUTES[pSection->Type].name,
|
||||
pSection->nBank);
|
||||
} else {
|
||||
errx(1, "Unable to place '%s' (%s section) in bank $%02lX (with $%lX-byte alignment)",
|
||||
pSection->pzName,
|
||||
SECT_ATTRIBUTES[pSection->Type].name,
|
||||
pSection->nBank, pSection->nAlign);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
AssignFloatingBankSections(enum eSectionType type)
|
||||
void AssignFloatingBankSections(enum eSectionType type)
|
||||
{
|
||||
ensureSectionTypeIsValid(type);
|
||||
|
||||
@@ -335,41 +384,45 @@ AssignFloatingBankSections(enum eSectionType type)
|
||||
while ((pSection = FindLargestSection(type, false))) {
|
||||
int32_t org;
|
||||
|
||||
if ((org = area_AllocAnyBank(pSection->nByteSize, pSection->nAlign, type)) != -1) {
|
||||
if (options & OPT_OVERLAY) {
|
||||
org = area_AllocAnyBank(pSection->nByteSize, pSection->nAlign,
|
||||
type);
|
||||
|
||||
if (org != -1) {
|
||||
if (options & OPT_OVERLAY)
|
||||
errx(1, "All sections must be fixed when using an overlay file.");
|
||||
}
|
||||
|
||||
pSection->nOrg = org & 0xFFFF;
|
||||
pSection->nBank = org >> 16;
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXBANK(pSection->Type, pSection->nBank);
|
||||
do_max_bank(pSection->Type, pSection->nBank);
|
||||
} else {
|
||||
const char *locality = "anywhere";
|
||||
if (SECT_ATTRIBUTES[pSection->Type].bankCount > 1) {
|
||||
|
||||
if (SECT_ATTRIBUTES[pSection->Type].bankCount > 1)
|
||||
locality = "in any bank";
|
||||
}
|
||||
|
||||
if (pSection->nAlign <= 1) {
|
||||
errx(1, "Unable to place '%s' (%s section) %s",
|
||||
pSection->pzName, SECT_ATTRIBUTES[type].name, locality);
|
||||
pSection->pzName,
|
||||
SECT_ATTRIBUTES[type].name, locality);
|
||||
} else {
|
||||
errx(1, "Unable to place '%s' (%s section) %s (with $%lX-byte alignment)",
|
||||
pSection->pzName, SECT_ATTRIBUTES[type].name, locality, pSection->nAlign);
|
||||
pSection->pzName,
|
||||
SECT_ATTRIBUTES[type].name, locality,
|
||||
pSection->nAlign);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
char *tzLinkerscriptName = NULL;
|
||||
char *tzLinkerscriptName;
|
||||
|
||||
void
|
||||
SetLinkerscriptName(char *tzLinkerscriptFile)
|
||||
void SetLinkerscriptName(char *tzLinkerscriptFile)
|
||||
{
|
||||
tzLinkerscriptName = tzLinkerscriptFile;
|
||||
}
|
||||
|
||||
void
|
||||
AssignSections(void)
|
||||
void AssignSections(void)
|
||||
{
|
||||
int32_t i;
|
||||
struct sSection *pSection;
|
||||
@@ -378,24 +431,21 @@ AssignSections(void)
|
||||
|
||||
/*
|
||||
* Initialize the memory areas
|
||||
*
|
||||
*/
|
||||
|
||||
for (i = 0; i < MAXBANKS; i += 1) {
|
||||
BankFree[i] = malloc(sizeof *BankFree[i]);
|
||||
BankFree[i] = malloc(sizeof(*BankFree[i]));
|
||||
|
||||
if (!BankFree[i]) {
|
||||
if (!BankFree[i])
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
if (i == BANK_ROM0) {
|
||||
/* ROM0 bank */
|
||||
BankFree[i]->nOrg = 0x0000;
|
||||
if (options & OPT_TINY) {
|
||||
if (options & OPT_TINY)
|
||||
BankFree[i]->nSize = 0x8000;
|
||||
} else {
|
||||
else
|
||||
BankFree[i]->nSize = 0x4000;
|
||||
}
|
||||
} else if (i >= BANK_ROMX && i < BANK_ROMX + BANK_COUNT_ROMX) {
|
||||
/* Swappable ROM bank */
|
||||
BankFree[i]->nOrg = 0x4000;
|
||||
@@ -403,11 +453,10 @@ AssignSections(void)
|
||||
} else if (i == BANK_WRAM0) {
|
||||
/* WRAM */
|
||||
BankFree[i]->nOrg = 0xC000;
|
||||
if (options & OPT_CONTWRAM) {
|
||||
if (options & OPT_CONTWRAM)
|
||||
BankFree[i]->nSize = 0x2000;
|
||||
} else {
|
||||
else
|
||||
BankFree[i]->nSize = 0x1000;
|
||||
}
|
||||
} else if (i >= BANK_SRAM && i < BANK_SRAM + BANK_COUNT_SRAM) {
|
||||
/* Swappable SRAM bank */
|
||||
BankFree[i]->nOrg = 0xA000;
|
||||
@@ -419,11 +468,10 @@ AssignSections(void)
|
||||
} else if (i >= BANK_VRAM && i < BANK_VRAM + BANK_COUNT_VRAM) {
|
||||
/* Swappable VRAM bank */
|
||||
BankFree[i]->nOrg = 0x8000;
|
||||
if (options & OPT_DMG_MODE && i != BANK_VRAM) {
|
||||
if (options & OPT_DMG_MODE && i != BANK_VRAM)
|
||||
BankFree[i]->nSize = 0;
|
||||
} else {
|
||||
else
|
||||
BankFree[i]->nSize = 0x2000;
|
||||
}
|
||||
} else if (i == BANK_OAM) {
|
||||
BankFree[i]->nOrg = 0xFE00;
|
||||
BankFree[i]->nSize = 0x00A0;
|
||||
@@ -442,7 +490,6 @@ AssignSections(void)
|
||||
|
||||
/*
|
||||
* First, let's parse the linkerscript.
|
||||
*
|
||||
*/
|
||||
|
||||
if (tzLinkerscriptName) {
|
||||
@@ -452,106 +499,109 @@ AssignSections(void)
|
||||
|
||||
/*
|
||||
* Second, let's assign all the fixed sections...
|
||||
*
|
||||
*/
|
||||
|
||||
pSection = pSections;
|
||||
while (pSection) {
|
||||
if ((pSection->nOrg != -1 || pSection->nBank != -1)
|
||||
&& pSection->oAssigned == 0) {
|
||||
/* User wants to have a say... */
|
||||
for (pSection = pSections ; pSection; pSection = pSection->pNext) {
|
||||
if (!((pSection->nOrg != -1 || pSection->nBank != -1)
|
||||
&& pSection->oAssigned == 0))
|
||||
continue;
|
||||
|
||||
switch (pSection->Type) {
|
||||
case SECT_WRAM0:
|
||||
case SECT_HRAM:
|
||||
case SECT_ROM0:
|
||||
case SECT_OAM:
|
||||
pSection->nBank = SECT_ATTRIBUTES[pSection->Type].bank;
|
||||
if (area_AllocAbs(&BankFree[pSection->nBank], pSection->nOrg,
|
||||
pSection->nByteSize) == -1) {
|
||||
errx(1, "Unable to place '%s' (%s section) at $%lX",
|
||||
pSection->pzName, SECT_ATTRIBUTES[pSection->Type].name, pSection->nOrg);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
break;
|
||||
/* User wants to have a say... */
|
||||
|
||||
case SECT_SRAM:
|
||||
case SECT_WRAMX:
|
||||
case SECT_VRAM:
|
||||
case SECT_ROMX:
|
||||
if (pSection->nBank != -1 && pSection->nOrg != -1) {
|
||||
if (VerifyAndSetBank(pSection) &&
|
||||
area_AllocAbs(&BankFree[pSection->nBank], pSection->nOrg, pSection->nByteSize) != -1) {
|
||||
DOMAXBANK(pSection->Type, pSection->nBank);
|
||||
pSection->oAssigned = 1;
|
||||
} else {
|
||||
errx(1, "Unable to place '%s' (%s section) at $%lX in bank $%02lX",
|
||||
pSection->pzName, SECT_ATTRIBUTES[pSection->Type].name, pSection->nOrg, pSection->nBank);
|
||||
}
|
||||
}
|
||||
break;
|
||||
switch (pSection->Type) {
|
||||
case SECT_WRAM0:
|
||||
case SECT_HRAM:
|
||||
case SECT_ROM0:
|
||||
case SECT_OAM:
|
||||
pSection->nBank = SECT_ATTRIBUTES[pSection->Type].bank;
|
||||
if (area_AllocAbs(&BankFree[pSection->nBank],
|
||||
pSection->nOrg,
|
||||
pSection->nByteSize) == -1) {
|
||||
errx(1, "Unable to place '%s' (%s section) at $%X",
|
||||
pSection->pzName,
|
||||
SECT_ATTRIBUTES[pSection->Type].name,
|
||||
pSection->nOrg);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
break;
|
||||
|
||||
case SECT_SRAM:
|
||||
case SECT_WRAMX:
|
||||
case SECT_VRAM:
|
||||
case SECT_ROMX:
|
||||
if (!(pSection->nBank != -1 && pSection->nOrg != -1))
|
||||
break;
|
||||
|
||||
if (VerifyAndSetBank(pSection) &&
|
||||
area_AllocAbs(&BankFree[pSection->nBank],
|
||||
pSection->nOrg,
|
||||
pSection->nByteSize) != -1) {
|
||||
do_max_bank(pSection->Type, pSection->nBank);
|
||||
pSection->oAssigned = 1;
|
||||
} else {
|
||||
errx(1, "Unable to place '%s' (%s section) at $%X in bank $%02X",
|
||||
pSection->pzName,
|
||||
SECT_ATTRIBUTES[pSection->Type].name,
|
||||
pSection->nOrg, pSection->nBank);
|
||||
}
|
||||
break;
|
||||
}
|
||||
pSection = pSection->pNext;
|
||||
}
|
||||
|
||||
/*
|
||||
* Next, let's assign all the bankfixed ONLY sections...
|
||||
*
|
||||
*/
|
||||
for (enum eSectionType i = SECT_MIN; i <= SECT_MAX; i++) {
|
||||
for (enum eSectionType i = SECT_MIN; i <= SECT_MAX; i++)
|
||||
AssignFixedBankSections(i);
|
||||
}
|
||||
|
||||
/*
|
||||
* Now, let's assign all the floating bank but fixed ROMX sections...
|
||||
*
|
||||
*/
|
||||
|
||||
pSection = pSections;
|
||||
while (pSection) {
|
||||
if (pSection->oAssigned == 0
|
||||
&& pSection->nOrg != -1 && pSection->nBank == -1) {
|
||||
if (options & OPT_OVERLAY) {
|
||||
errx(1, "All sections must be fixed when using an overlay file.");
|
||||
}
|
||||
switch (pSection->Type) {
|
||||
case SECT_ROMX:
|
||||
case SECT_VRAM:
|
||||
case SECT_SRAM:
|
||||
case SECT_WRAMX:
|
||||
if ((pSection->nBank =
|
||||
area_AllocAbsAnyBank(pSection->nOrg, pSection->nByteSize,
|
||||
pSection->Type)) == -1) {
|
||||
errx(1, "Unable to place '%s' (%s section) at $%lX in any bank",
|
||||
pSection->pzName, SECT_ATTRIBUTES[pSection->Type].name, pSection->nOrg);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
DOMAXBANK(pSection->Type, pSection->nBank);
|
||||
break;
|
||||
for (pSection = pSections ; pSection; pSection = pSection->pNext) {
|
||||
if (!(pSection->oAssigned == 0
|
||||
&& pSection->nOrg != -1 && pSection->nBank == -1))
|
||||
continue;
|
||||
|
||||
default: // Handle other sections later
|
||||
break;
|
||||
if (options & OPT_OVERLAY)
|
||||
errx(1, "All sections must be fixed when using an overlay file.");
|
||||
|
||||
switch (pSection->Type) {
|
||||
case SECT_ROMX:
|
||||
case SECT_VRAM:
|
||||
case SECT_SRAM:
|
||||
case SECT_WRAMX:
|
||||
pSection->nBank =
|
||||
area_AllocAbsAnyBank(pSection->nOrg,
|
||||
pSection->nByteSize,
|
||||
pSection->Type);
|
||||
|
||||
if (pSection->nBank == -1) {
|
||||
errx(1, "Unable to place '%s' (%s section) at $%X in any bank",
|
||||
pSection->pzName,
|
||||
SECT_ATTRIBUTES[pSection->Type].name,
|
||||
pSection->nOrg);
|
||||
}
|
||||
pSection->oAssigned = 1;
|
||||
do_max_bank(pSection->Type, pSection->nBank);
|
||||
break;
|
||||
|
||||
default: /* Handle other sections later */
|
||||
break;
|
||||
}
|
||||
|
||||
pSection = pSection->pNext;
|
||||
}
|
||||
|
||||
/*
|
||||
* OK, all that nasty stuff is done so let's assign all the other
|
||||
* sections
|
||||
*
|
||||
*/
|
||||
for (enum eSectionType i = SECT_MIN; i <= SECT_MAX; i++) {
|
||||
for (enum eSectionType i = SECT_MIN; i <= SECT_MAX; i++)
|
||||
AssignFloatingBankSections(i);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
CreateSymbolTable(void)
|
||||
void CreateSymbolTable(void)
|
||||
{
|
||||
struct sSection *pSect;
|
||||
const struct sSection *pSect;
|
||||
|
||||
sym_Init();
|
||||
|
||||
@@ -563,25 +613,27 @@ CreateSymbolTable(void)
|
||||
i = pSect->nNumberOfSymbols;
|
||||
|
||||
while (i--) {
|
||||
if ((pSect->tSymbols[i]->Type == SYM_EXPORT) &&
|
||||
((pSect->tSymbols[i]->pSection == pSect) ||
|
||||
(pSect->tSymbols[i]->pSection == NULL))) {
|
||||
if (pSect->tSymbols[i]->pSection == NULL)
|
||||
const struct sSymbol *tSymbol = pSect->tSymbols[i];
|
||||
|
||||
if ((tSymbol->Type == SYM_EXPORT) &&
|
||||
((tSymbol->pSection == pSect) ||
|
||||
(tSymbol->pSection == NULL))) {
|
||||
if (tSymbol->pSection == NULL)
|
||||
sym_CreateSymbol(
|
||||
pSect->tSymbols[i]->pzName,
|
||||
pSect->tSymbols[i]->nOffset,
|
||||
tSymbol->pzName,
|
||||
tSymbol->nOffset,
|
||||
-1,
|
||||
pSect->tSymbols[i]->pzObjFileName,
|
||||
pSect->tSymbols[i]->pzFileName,
|
||||
pSect->tSymbols[i]->nFileLine);
|
||||
tSymbol->pzObjFileName,
|
||||
tSymbol->pzFileName,
|
||||
tSymbol->nFileLine);
|
||||
else
|
||||
sym_CreateSymbol(
|
||||
pSect->tSymbols[i]->pzName,
|
||||
pSect->nOrg + pSect->tSymbols[i]->nOffset,
|
||||
tSymbol->pzName,
|
||||
pSect->nOrg + tSymbol->nOffset,
|
||||
pSect->nBank,
|
||||
pSect->tSymbols[i]->pzObjFileName,
|
||||
pSect->tSymbols[i]->pzFileName,
|
||||
pSect->tSymbols[i]->nFileLine);
|
||||
tSymbol->pzObjFileName,
|
||||
tSymbol->pzFileName,
|
||||
tSymbol->nFileLine);
|
||||
}
|
||||
}
|
||||
pSect = pSect->pNext;
|
||||
|
||||
@@ -35,9 +35,9 @@ extern int yyparse();
|
||||
|
||||
/* File include stack. */
|
||||
|
||||
#define MAX_INCLUDE_DEPTH 8
|
||||
#define MAX_INCLUDE_DEPTH 8
|
||||
|
||||
static int32_t include_stack_ptr = 0;
|
||||
static int32_t include_stack_ptr;
|
||||
|
||||
static YY_BUFFER_STATE include_stack[MAX_INCLUDE_DEPTH];
|
||||
static char include_path[MAX_INCLUDE_DEPTH][_MAX_PATH + 1];
|
||||
@@ -49,14 +49,21 @@ static char linkerscript_path[_MAX_PATH + 1]; /* Base file */
|
||||
%%
|
||||
|
||||
\"([^\\\"]|\\.)*\" {
|
||||
if (strlen(yytext) > sizeof(yylval.s) - 1)
|
||||
script_fatalerror("String is too long: %s\n.", yytext);
|
||||
if (strlen(yytext) < 3) /* 2 quotes + 1 character */
|
||||
script_fatalerror("String %s is invalid\n.", yytext);
|
||||
if (strlen(yytext) > sizeof(yylval.s) - 1) {
|
||||
script_fatalerror("String is too long: %s\n.",
|
||||
yytext);
|
||||
}
|
||||
|
||||
yytext++; /* ignore first quote */
|
||||
if (strlen(yytext) < 3) { /* 2 quotes + 1 character */
|
||||
script_fatalerror("String %s is invalid\n.",
|
||||
yytext);
|
||||
}
|
||||
|
||||
/* Ignore first quote */
|
||||
yytext++;
|
||||
strcpy(yylval.s, yytext);
|
||||
yylval.s[strlen(yylval.s)-1] = '\0'; /* remove end quote */
|
||||
/* Remove end quote */
|
||||
yylval.s[strlen(yylval.s)-1] = '\0';
|
||||
|
||||
return STRING;
|
||||
}
|
||||
@@ -112,12 +119,11 @@ void script_Parse(const char * path)
|
||||
} while (!feof(yyin));
|
||||
|
||||
fclose(yyin);
|
||||
|
||||
}
|
||||
|
||||
void script_IncludeFile(const char * path)
|
||||
{
|
||||
if (include_stack_ptr == (MAX_INCLUDE_DEPTH-1))
|
||||
if (include_stack_ptr == (MAX_INCLUDE_DEPTH - 1))
|
||||
script_fatalerror("Includes nested too deeply.");
|
||||
|
||||
include_line[include_stack_ptr] = yylineno;
|
||||
@@ -125,13 +131,13 @@ void script_IncludeFile(const char * path)
|
||||
|
||||
include_stack_ptr++;
|
||||
|
||||
yyin = fopen(path, "r" );
|
||||
yyin = fopen(path, "r");
|
||||
|
||||
if (!yyin)
|
||||
script_fatalerror("Couldn't open file \"%s\"", path);
|
||||
|
||||
strncpy(include_path[include_stack_ptr], path, sizeof(include_path[0]));
|
||||
include_path[include_stack_ptr][sizeof(include_path[0])-1] = '\0';
|
||||
include_path[include_stack_ptr][sizeof(include_path[0]) - 1] = '\0';
|
||||
|
||||
yy_switch_to_buffer(yy_create_buffer(yyin, YY_BUF_SIZE));
|
||||
yylineno = 1;
|
||||
|
||||
@@ -4,13 +4,13 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "extern/err.h"
|
||||
|
||||
#include "link/mylink.h"
|
||||
#include "link/main.h"
|
||||
|
||||
static uint8_t
|
||||
symboldefined(char *name)
|
||||
static uint8_t symboldefined(char *name)
|
||||
{
|
||||
struct sSection *pSect;
|
||||
const struct sSection *pSect;
|
||||
|
||||
pSect = pSections;
|
||||
|
||||
@@ -18,56 +18,54 @@ symboldefined(char *name)
|
||||
int32_t i;
|
||||
|
||||
for (i = 0; i < pSect->nNumberOfSymbols; i += 1) {
|
||||
if ((pSect->tSymbols[i]->Type == SYM_EXPORT)
|
||||
|| ((pSect->tSymbols[i]->Type == SYM_LOCAL)
|
||||
&& (pSect == pSect->tSymbols[i]->pSection))) {
|
||||
if (strcmp(pSect->tSymbols[i]->pzName, name) ==
|
||||
0)
|
||||
return (1);
|
||||
const struct sSymbol *tSymbol = pSect->tSymbols[i];
|
||||
|
||||
if ((tSymbol->Type == SYM_EXPORT)
|
||||
|| ((tSymbol->Type == SYM_LOCAL)
|
||||
&& (pSect == tSymbol->pSection))) {
|
||||
|
||||
if (strcmp(tSymbol->pzName, name) == 0)
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
pSect = pSect->pNext;
|
||||
}
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
static uint8_t
|
||||
addmodulecontaining(char *name)
|
||||
static uint8_t addmodulecontaining(char *name)
|
||||
{
|
||||
struct sSection **ppLSect;
|
||||
|
||||
ppLSect = &pLibSections;
|
||||
struct sSection **ppLSect = &pLibSections;
|
||||
|
||||
while (*ppLSect) {
|
||||
int32_t i;
|
||||
|
||||
for (i = 0; i < (*ppLSect)->nNumberOfSymbols; i += 1) {
|
||||
if (((*ppLSect)->tSymbols[i]->Type == SYM_EXPORT)
|
||||
|| (((*ppLSect)->tSymbols[i]->Type == SYM_LOCAL)
|
||||
&& ((*ppLSect) ==
|
||||
(*ppLSect)->tSymbols[i]->pSection))) {
|
||||
if (strcmp
|
||||
((*ppLSect)->tSymbols[i]->pzName,
|
||||
name) == 0) {
|
||||
struct sSection **ppSect;
|
||||
ppSect = &pSections;
|
||||
const struct sSymbol *tSymbol = (*ppLSect)->tSymbols[i];
|
||||
|
||||
if ((tSymbol->Type == SYM_EXPORT)
|
||||
|| ((tSymbol->Type == SYM_LOCAL)
|
||||
&& ((*ppLSect) == tSymbol->pSection))) {
|
||||
|
||||
if (strcmp(tSymbol->pzName, name) == 0) {
|
||||
struct sSection **ppSect = &pSections;
|
||||
|
||||
while (*ppSect)
|
||||
ppSect = &((*ppSect)->pNext);
|
||||
|
||||
*ppSect = *ppLSect;
|
||||
*ppLSect = (*ppLSect)->pNext;
|
||||
(*ppSect)->pNext = NULL;
|
||||
return (1);
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
}
|
||||
ppLSect = &((*ppLSect)->pNext);
|
||||
}
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
void
|
||||
AddNeededModules(void)
|
||||
void AddNeededModules(void)
|
||||
{
|
||||
struct sSection *pSect;
|
||||
|
||||
@@ -77,8 +75,8 @@ AddNeededModules(void)
|
||||
ppLSect = &pLibSections;
|
||||
|
||||
while (*ppLSect) {
|
||||
struct sSection **ppSect;
|
||||
ppSect = &pSections;
|
||||
struct sSection **ppSect = &pSections;
|
||||
|
||||
while (*ppSect)
|
||||
ppSect = &((*ppSect)->pNext);
|
||||
|
||||
@@ -93,10 +91,11 @@ AddNeededModules(void)
|
||||
if (options & OPT_SMART_C_LINK) {
|
||||
if (!addmodulecontaining(smartlinkstartsymbol)) {
|
||||
errx(1, "Can't find start symbol '%s'",
|
||||
smartlinkstartsymbol);
|
||||
} else
|
||||
smartlinkstartsymbol);
|
||||
} else {
|
||||
printf("Smart linking with symbol '%s'\n",
|
||||
smartlinkstartsymbol);
|
||||
smartlinkstartsymbol);
|
||||
}
|
||||
}
|
||||
pSect = pSections;
|
||||
|
||||
@@ -106,10 +105,8 @@ AddNeededModules(void)
|
||||
for (i = 0; i < pSect->nNumberOfSymbols; i += 1) {
|
||||
if ((pSect->tSymbols[i]->Type == SYM_IMPORT)
|
||||
|| (pSect->tSymbols[i]->Type == SYM_LOCAL)) {
|
||||
if (!symboldefined(pSect->tSymbols[i]->pzName)) {
|
||||
addmodulecontaining(pSect->tSymbols[i]->
|
||||
pzName);
|
||||
}
|
||||
if (!symboldefined(pSect->tSymbols[i]->pzName))
|
||||
addmodulecontaining(pSect->tSymbols[i]->pzName);
|
||||
}
|
||||
}
|
||||
pSect = pSect->pNext;
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
|
||||
#include "extern/err.h"
|
||||
#include "extern/version.h"
|
||||
|
||||
#include "link/object.h"
|
||||
#include "link/output.h"
|
||||
#include "link/assign.h"
|
||||
@@ -22,17 +23,15 @@ enum eBlockType {
|
||||
BLOCK_OUTPUT
|
||||
};
|
||||
|
||||
int32_t options = 0;
|
||||
int32_t fillchar = 0;
|
||||
int32_t options;
|
||||
int32_t fillchar;
|
||||
char *smartlinkstartsymbol;
|
||||
|
||||
/*
|
||||
* Print the usagescreen
|
||||
*
|
||||
*/
|
||||
|
||||
static void
|
||||
usage(void)
|
||||
static void print_usage(void)
|
||||
{
|
||||
printf(
|
||||
"usage: rgblink [-dtVw] [-l linkerscript] [-m mapfile] [-n symfile] [-O overlay]\n"
|
||||
@@ -42,17 +41,15 @@ usage(void)
|
||||
|
||||
/*
|
||||
* The main routine
|
||||
*
|
||||
*/
|
||||
|
||||
int
|
||||
main(int argc, char *argv[])
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
int ch;
|
||||
char *ep;
|
||||
|
||||
if (argc == 1)
|
||||
usage();
|
||||
print_usage();
|
||||
|
||||
while ((ch = getopt(argc, argv, "dl:m:n:O:o:p:s:tVw")) != -1) {
|
||||
switch (ch) {
|
||||
@@ -74,12 +71,10 @@ main(int argc, char *argv[])
|
||||
break;
|
||||
case 'p':
|
||||
fillchar = strtoul(optarg, &ep, 0);
|
||||
if (optarg[0] == '\0' || *ep != '\0') {
|
||||
if (optarg[0] == '\0' || *ep != '\0')
|
||||
errx(1, "Invalid argument for option 'p'");
|
||||
}
|
||||
if (fillchar < 0 || fillchar > 0xFF) {
|
||||
if (fillchar < 0 || fillchar > 0xFF)
|
||||
errx(1, "Argument for option 'p' must be between 0 and 0xFF");
|
||||
}
|
||||
break;
|
||||
case 's':
|
||||
options |= OPT_SMART_C_LINK;
|
||||
@@ -101,17 +96,19 @@ main(int argc, char *argv[])
|
||||
options |= OPT_DMG_MODE;
|
||||
/* FALLTHROUGH */
|
||||
case 'w':
|
||||
/* Set to set WRAM as a single continuous block as on
|
||||
/*
|
||||
* Set to set WRAM as a single continuous block as on
|
||||
* DMG. All WRAM sections must be WRAM0 as bankable WRAM
|
||||
* sections do not exist in this mode. A WRAMX section
|
||||
* will raise an error. */
|
||||
* will raise an error.
|
||||
*/
|
||||
options |= OPT_CONTWRAM;
|
||||
break;
|
||||
case 'V':
|
||||
printf("rgblink %s\n", get_package_version_string());
|
||||
exit(0);
|
||||
default:
|
||||
usage();
|
||||
print_usage();
|
||||
/* NOTREACHED */
|
||||
}
|
||||
}
|
||||
@@ -119,7 +116,7 @@ main(int argc, char *argv[])
|
||||
argv += optind;
|
||||
|
||||
if (argc == 0)
|
||||
usage();
|
||||
print_usage();
|
||||
|
||||
for (int32_t i = 0; i < argc; ++i)
|
||||
obj_Readfile(argv[i]);
|
||||
@@ -131,5 +128,5 @@ main(int argc, char *argv[])
|
||||
Output();
|
||||
CloseMapfile();
|
||||
|
||||
return (0);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@@ -5,39 +5,35 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "extern/err.h"
|
||||
|
||||
#include "link/main.h"
|
||||
#include "link/mylink.h"
|
||||
#include "link/assign.h"
|
||||
|
||||
FILE *mf = NULL;
|
||||
FILE *sf = NULL;
|
||||
int32_t currentbank = 0;
|
||||
int32_t sfbank;
|
||||
static int32_t currentbank;
|
||||
static int32_t sfbank;
|
||||
static FILE *mf;
|
||||
static FILE *sf;
|
||||
|
||||
void
|
||||
SetMapfileName(char *name)
|
||||
void SetMapfileName(char *name)
|
||||
{
|
||||
mf = fopen(name, "w");
|
||||
|
||||
if (mf == NULL) {
|
||||
if (mf == NULL)
|
||||
err(1, "Cannot open mapfile '%s'", name);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
SetSymfileName(char *name)
|
||||
void SetSymfileName(char *name)
|
||||
{
|
||||
sf = fopen(name, "w");
|
||||
|
||||
if (sf == NULL) {
|
||||
if (sf == NULL)
|
||||
err(1, "Cannot open symfile '%s'", name);
|
||||
}
|
||||
|
||||
fprintf(sf, ";File generated by rgblink\n\n");
|
||||
fprintf(sf, "; File generated by rgblink\n\n");
|
||||
}
|
||||
|
||||
void
|
||||
CloseMapfile(void)
|
||||
void CloseMapfile(void)
|
||||
{
|
||||
if (mf) {
|
||||
fclose(mf);
|
||||
@@ -49,8 +45,7 @@ CloseMapfile(void)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MapfileInitBank(int32_t bank)
|
||||
void MapfileInitBank(int32_t bank)
|
||||
{
|
||||
if (mf) {
|
||||
currentbank = bank;
|
||||
@@ -91,8 +86,7 @@ MapfileInitBank(int32_t bank)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MapfileWriteSection(struct sSection * pSect)
|
||||
void MapfileWriteSection(const struct sSection *pSect)
|
||||
{
|
||||
int32_t i;
|
||||
|
||||
@@ -108,26 +102,24 @@ MapfileWriteSection(struct sSection * pSect)
|
||||
}
|
||||
|
||||
for (i = 0; i < pSect->nNumberOfSymbols; i += 1) {
|
||||
struct sSymbol *pSym;
|
||||
pSym = pSect->tSymbols[i];
|
||||
if ((pSym->pSection == pSect)
|
||||
&& (pSym->Type != SYM_IMPORT)) {
|
||||
const struct sSymbol *pSym = pSect->tSymbols[i];
|
||||
|
||||
if ((pSym->pSection == pSect) && (pSym->Type != SYM_IMPORT)) {
|
||||
if (mf) {
|
||||
fprintf(mf, " $%04X = %s\n",
|
||||
pSym->nOffset + pSect->nOrg,
|
||||
pSym->pzName);
|
||||
pSym->nOffset + pSect->nOrg,
|
||||
pSym->pzName);
|
||||
}
|
||||
if (sf) {
|
||||
fprintf(sf, "%02X:%04X %s\n", sfbank,
|
||||
pSym->nOffset + pSect->nOrg,
|
||||
pSym->pzName);
|
||||
pSym->nOffset + pSect->nOrg,
|
||||
pSym->pzName);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
MapfileCloseBank(int32_t slack)
|
||||
void MapfileCloseBank(int32_t slack)
|
||||
{
|
||||
if (!mf)
|
||||
return;
|
||||
|
||||
@@ -1,6 +1,5 @@
|
||||
/*
|
||||
* Here we have the routines that read an objectfile
|
||||
*
|
||||
*/
|
||||
|
||||
#include <ctype.h>
|
||||
@@ -11,24 +10,23 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "common.h"
|
||||
|
||||
#include "extern/err.h"
|
||||
|
||||
#include "link/assign.h"
|
||||
#include "link/mylink.h"
|
||||
#include "link/main.h"
|
||||
|
||||
struct sSymbol **tSymbols;
|
||||
struct sSection *pSections = NULL;
|
||||
struct sSection *pLibSections = NULL;
|
||||
struct sSection *pSections;
|
||||
struct sSection *pLibSections;
|
||||
uint8_t dummymem;
|
||||
uint8_t oReadLib = 0;
|
||||
uint8_t oReadLib;
|
||||
|
||||
/*
|
||||
* The usual byte order stuff
|
||||
*
|
||||
* Read 32-bit values with the correct endianness
|
||||
*/
|
||||
|
||||
int32_t
|
||||
readlong(FILE * f)
|
||||
static int32_t readlong(FILE *f)
|
||||
{
|
||||
int32_t r;
|
||||
|
||||
@@ -37,26 +35,13 @@ readlong(FILE * f)
|
||||
r |= fgetc(f) << 16;
|
||||
r |= fgetc(f) << 24;
|
||||
|
||||
return (r);
|
||||
}
|
||||
|
||||
uint16_t
|
||||
readword(FILE * f)
|
||||
{
|
||||
uint16_t r;
|
||||
|
||||
r = fgetc(f);
|
||||
r |= fgetc(f) << 8;
|
||||
|
||||
return (r);
|
||||
return r;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a NULL terminated string from a file
|
||||
*
|
||||
*/
|
||||
int32_t
|
||||
readasciiz(char **dest, FILE *f)
|
||||
int32_t readasciiz(char **dest, FILE *f)
|
||||
{
|
||||
size_t r = 0;
|
||||
|
||||
@@ -64,9 +49,8 @@ readasciiz(char **dest, FILE *f)
|
||||
char *start = malloc(bufferLength);
|
||||
char *s = start;
|
||||
|
||||
if (!s) {
|
||||
if (!s)
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
while (((*s++) = fgetc(f)) != 0) {
|
||||
r += 1;
|
||||
@@ -74,9 +58,8 @@ readasciiz(char **dest, FILE *f)
|
||||
if (r >= bufferLength) {
|
||||
bufferLength *= 2;
|
||||
start = realloc(start, bufferLength);
|
||||
if (!start) {
|
||||
if (!start)
|
||||
err(1, NULL);
|
||||
}
|
||||
s = start + r;
|
||||
}
|
||||
}
|
||||
@@ -87,11 +70,8 @@ readasciiz(char **dest, FILE *f)
|
||||
|
||||
/*
|
||||
* Allocate a new section and link it into the list
|
||||
*
|
||||
*/
|
||||
|
||||
struct sSection *
|
||||
AllocSection(void)
|
||||
struct sSection *AllocSection(void)
|
||||
{
|
||||
struct sSection **ppSections;
|
||||
|
||||
@@ -104,29 +84,26 @@ AllocSection(void)
|
||||
ppSections = &((*ppSections)->pNext);
|
||||
|
||||
*ppSections = malloc(sizeof **ppSections);
|
||||
if (!*ppSections) {
|
||||
if (!*ppSections)
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
(*ppSections)->tSymbols = tSymbols;
|
||||
(*ppSections)->pNext = NULL;
|
||||
(*ppSections)->pPatches = NULL;
|
||||
(*ppSections)->oAssigned = 0;
|
||||
return *ppSections;
|
||||
}
|
||||
|
||||
/*
|
||||
* Read a symbol from a file
|
||||
*
|
||||
*/
|
||||
|
||||
struct sSymbol *
|
||||
obj_ReadSymbol(FILE * f, char *tzObjectfile)
|
||||
struct sSymbol *obj_ReadSymbol(FILE *f, char *tzObjectfile)
|
||||
{
|
||||
struct sSymbol *pSym;
|
||||
|
||||
pSym = malloc(sizeof *pSym);
|
||||
if (!pSym) {
|
||||
pSym = malloc(sizeof(*pSym));
|
||||
if (!pSym)
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
readasciiz(&pSym->pzName, f);
|
||||
pSym->Type = (enum eSymbolType)fgetc(f);
|
||||
@@ -140,19 +117,18 @@ obj_ReadSymbol(FILE * f, char *tzObjectfile)
|
||||
pSym->nSectionID = readlong(f);
|
||||
pSym->nOffset = readlong(f);
|
||||
}
|
||||
|
||||
return pSym;
|
||||
}
|
||||
|
||||
/*
|
||||
* RGB object reader routines
|
||||
*
|
||||
*/
|
||||
struct sSection *
|
||||
obj_ReadRGBSection(FILE * f)
|
||||
struct sSection *obj_ReadRGBSection(FILE *f)
|
||||
{
|
||||
struct sSection *pSection;
|
||||
|
||||
char *pzName;
|
||||
|
||||
readasciiz(&pzName, f);
|
||||
if (IsSectionNameInUse(pzName))
|
||||
errx(1, "Section name \"%s\" is already in use.", pzName);
|
||||
@@ -161,124 +137,123 @@ obj_ReadRGBSection(FILE * f)
|
||||
pSection->pzName = pzName;
|
||||
|
||||
pSection->nByteSize = readlong(f);
|
||||
pSection->Type = (enum eSectionType) fgetc(f);
|
||||
pSection->Type = (enum eSectionType)fgetc(f);
|
||||
pSection->nOrg = readlong(f);
|
||||
pSection->nBank = readlong(f);
|
||||
pSection->nAlign = readlong(f);
|
||||
|
||||
if ((options & OPT_TINY) && (pSection->Type == SECT_ROMX)) {
|
||||
if ((options & OPT_TINY) && (pSection->Type == SECT_ROMX))
|
||||
errx(1, "ROMX sections can't be used with option -t.");
|
||||
}
|
||||
if ((options & OPT_CONTWRAM) && (pSection->Type == SECT_WRAMX)) {
|
||||
|
||||
if ((options & OPT_CONTWRAM) && (pSection->Type == SECT_WRAMX))
|
||||
errx(1, "WRAMX sections can't be used with options -w or -d.");
|
||||
}
|
||||
|
||||
if (options & OPT_DMG_MODE) {
|
||||
/* WRAMX sections are checked for OPT_CONTWRAM */
|
||||
if (pSection->Type == SECT_VRAM && pSection->nBank == 1) {
|
||||
if (pSection->Type == SECT_VRAM && pSection->nBank == 1)
|
||||
errx(1, "VRAM bank 1 can't be used with option -d.");
|
||||
}
|
||||
}
|
||||
|
||||
uint32_t maxsize = 0;
|
||||
|
||||
/* Verify that the section isn't too big */
|
||||
switch (pSection->Type)
|
||||
{
|
||||
case SECT_ROM0:
|
||||
maxsize = (options & OPT_TINY) ? 0x8000 : 0x4000;
|
||||
break;
|
||||
case SECT_ROMX:
|
||||
maxsize = 0x4000;
|
||||
break;
|
||||
case SECT_VRAM:
|
||||
case SECT_SRAM:
|
||||
maxsize = 0x2000;
|
||||
break;
|
||||
case SECT_WRAM0:
|
||||
maxsize = (options & OPT_CONTWRAM) ? 0x2000 : 0x1000;
|
||||
break;
|
||||
case SECT_WRAMX:
|
||||
maxsize = 0x1000;
|
||||
break;
|
||||
case SECT_OAM:
|
||||
maxsize = 0xA0;
|
||||
break;
|
||||
case SECT_HRAM:
|
||||
maxsize = 0x7F;
|
||||
break;
|
||||
default:
|
||||
errx(1, "Section \"%s\" has an invalid section type.", pzName);
|
||||
break;
|
||||
switch (pSection->Type) {
|
||||
case SECT_ROM0:
|
||||
maxsize = (options & OPT_TINY) ? 0x8000 : 0x4000;
|
||||
break;
|
||||
case SECT_ROMX:
|
||||
maxsize = 0x4000;
|
||||
break;
|
||||
case SECT_VRAM:
|
||||
case SECT_SRAM:
|
||||
maxsize = 0x2000;
|
||||
break;
|
||||
case SECT_WRAM0:
|
||||
maxsize = (options & OPT_CONTWRAM) ? 0x2000 : 0x1000;
|
||||
break;
|
||||
case SECT_WRAMX:
|
||||
maxsize = 0x1000;
|
||||
break;
|
||||
case SECT_OAM:
|
||||
maxsize = 0xA0;
|
||||
break;
|
||||
case SECT_HRAM:
|
||||
maxsize = 0x7F;
|
||||
break;
|
||||
default:
|
||||
errx(1, "Section \"%s\" has an invalid section type.", pzName);
|
||||
break;
|
||||
}
|
||||
if (pSection->nByteSize > maxsize) {
|
||||
errx(1, "Section \"%s\" is bigger than the max size for that type: 0x%X > 0x%X",
|
||||
pzName, pSection->nByteSize, maxsize);
|
||||
pzName, pSection->nByteSize, maxsize);
|
||||
}
|
||||
|
||||
if ((pSection->Type == SECT_ROMX) || (pSection->Type == SECT_ROM0)) {
|
||||
/*
|
||||
* These sectiontypes contain data...
|
||||
*
|
||||
*/
|
||||
if (pSection->nByteSize) {
|
||||
pSection->pData = malloc(pSection->nByteSize);
|
||||
if (!pSection->pData) {
|
||||
/*
|
||||
* If the section doesn't contain data, it is ready
|
||||
*/
|
||||
if ((pSection->Type != SECT_ROMX) && (pSection->Type != SECT_ROM0))
|
||||
return pSection;
|
||||
|
||||
/* If there is no data to read, exit */
|
||||
if (pSection->nByteSize == 0) {
|
||||
/* Skip number of patches */
|
||||
readlong(f);
|
||||
pSection->pData = &dummymem;
|
||||
return pSection;
|
||||
}
|
||||
|
||||
pSection->pData = malloc(pSection->nByteSize);
|
||||
if (!pSection->pData)
|
||||
err(1, NULL);
|
||||
|
||||
int32_t nNumberOfPatches;
|
||||
struct sPatch **ppPatch, *pPatch;
|
||||
|
||||
if (fread(pSection->pData, sizeof(uint8_t), pSection->nByteSize, f)
|
||||
!= pSection->nByteSize) {
|
||||
err(1, "Read error.");
|
||||
}
|
||||
|
||||
nNumberOfPatches = readlong(f);
|
||||
ppPatch = &pSection->pPatches;
|
||||
|
||||
/*
|
||||
* And patches...
|
||||
*/
|
||||
while (nNumberOfPatches--) {
|
||||
pPatch = malloc(sizeof(*pPatch));
|
||||
if (!pPatch)
|
||||
err(1, NULL);
|
||||
|
||||
*ppPatch = pPatch;
|
||||
readasciiz(&pPatch->pzFilename, f);
|
||||
pPatch->nLineNo = readlong(f);
|
||||
pPatch->nOffset = readlong(f);
|
||||
pPatch->Type = (enum ePatchType)fgetc(f);
|
||||
pPatch->nRPNSize = readlong(f);
|
||||
|
||||
if (pPatch->nRPNSize > 0) {
|
||||
pPatch->pRPN = malloc(pPatch->nRPNSize);
|
||||
if (!pPatch->pRPN)
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
int32_t nNumberOfPatches;
|
||||
struct sPatch **ppPatch, *pPatch;
|
||||
|
||||
if (fread(pSection->pData, sizeof(uint8_t),
|
||||
pSection->nByteSize, f) != pSection->nByteSize) {
|
||||
err(1, "Read error.");
|
||||
}
|
||||
|
||||
nNumberOfPatches = readlong(f);
|
||||
ppPatch = &pSection->pPatches;
|
||||
|
||||
/*
|
||||
* And patches...
|
||||
*
|
||||
*/
|
||||
while (nNumberOfPatches--) {
|
||||
pPatch = malloc(sizeof *pPatch);
|
||||
if (!pPatch) {
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
*ppPatch = pPatch;
|
||||
readasciiz(&pPatch->pzFilename, f);
|
||||
pPatch->nLineNo = readlong(f);
|
||||
pPatch->nOffset = readlong(f);
|
||||
pPatch->Type = (enum ePatchType) fgetc(f);
|
||||
if ((pPatch->nRPNSize = readlong(f)) > 0) {
|
||||
pPatch->pRPN = malloc(pPatch->nRPNSize);
|
||||
if (!pPatch->pRPN) {
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
if (fread(pPatch->pRPN, sizeof(uint8_t),
|
||||
pPatch->nRPNSize, f) != pPatch->nRPNSize) {
|
||||
errx(1, "Read error.");
|
||||
}
|
||||
} else
|
||||
pPatch->pRPN = NULL;
|
||||
|
||||
pPatch->pNext = NULL;
|
||||
ppPatch = &(pPatch->pNext);
|
||||
if (fread(pPatch->pRPN, sizeof(uint8_t),
|
||||
pPatch->nRPNSize, f) != pPatch->nRPNSize) {
|
||||
errx(1, "Read error.");
|
||||
}
|
||||
} else {
|
||||
/* Skip number of patches */
|
||||
readlong(f);
|
||||
pSection->pData = &dummymem;
|
||||
pPatch->pRPN = NULL;
|
||||
}
|
||||
|
||||
pPatch->pNext = NULL;
|
||||
ppPatch = &(pPatch->pNext);
|
||||
}
|
||||
|
||||
return pSection;
|
||||
}
|
||||
|
||||
void
|
||||
obj_ReadRGB(FILE * pObjfile, char *tzObjectfile)
|
||||
void obj_ReadRGB(FILE *pObjfile, char *tzObjectfile)
|
||||
{
|
||||
struct sSection *pFirstSection;
|
||||
int32_t nNumberOfSymbols, nNumberOfSections, i;
|
||||
@@ -289,15 +264,15 @@ obj_ReadRGB(FILE * pObjfile, char *tzObjectfile)
|
||||
/* First comes the symbols */
|
||||
|
||||
if (nNumberOfSymbols) {
|
||||
tSymbols = malloc(nNumberOfSymbols * sizeof *tSymbols);
|
||||
if (!tSymbols) {
|
||||
tSymbols = malloc(nNumberOfSymbols * sizeof(*tSymbols));
|
||||
if (!tSymbols)
|
||||
err(1, NULL);
|
||||
}
|
||||
|
||||
for (i = 0; i < nNumberOfSymbols; i += 1)
|
||||
tSymbols[i] = obj_ReadSymbol(pObjfile, tzObjectfile);
|
||||
} else
|
||||
tSymbols = (struct sSymbol **) & dummymem;
|
||||
} else {
|
||||
tSymbols = (struct sSymbol **)&dummymem;
|
||||
}
|
||||
|
||||
/* Next we have the sections */
|
||||
|
||||
@@ -314,55 +289,56 @@ obj_ReadRGB(FILE * pObjfile, char *tzObjectfile)
|
||||
/*
|
||||
* Fill in the pSection entry in the symbolstructure.
|
||||
* This REALLY needs some cleaning up... but, hey, it works
|
||||
*
|
||||
*/
|
||||
|
||||
for (i = 0; i < nNumberOfSymbols; i += 1) {
|
||||
struct sSection *pConvSect = pFirstSection;
|
||||
|
||||
if (tSymbols[i]->Type != SYM_IMPORT
|
||||
&& tSymbols[i]->nSectionID != -1) {
|
||||
if ((tSymbols[i]->Type != SYM_IMPORT) &&
|
||||
(tSymbols[i]->nSectionID != -1)) {
|
||||
int32_t j = 0;
|
||||
|
||||
while (j != tSymbols[i]->nSectionID) {
|
||||
j += 1;
|
||||
pConvSect = pConvSect->pNext;
|
||||
}
|
||||
tSymbols[i]->pSection = pConvSect;
|
||||
} else
|
||||
} else {
|
||||
tSymbols[i]->pSection = NULL;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* The main objectfileloadroutine (phew)
|
||||
*
|
||||
*/
|
||||
|
||||
void
|
||||
obj_ReadOpenFile(FILE * pObjfile, char *tzObjectfile)
|
||||
void obj_ReadOpenFile(FILE *pObjfile, char *tzObjectfile)
|
||||
{
|
||||
char tzHeader[strlen(RGBDS_OBJECT_VERSION_STRING) + 1];
|
||||
|
||||
if (fread(tzHeader, sizeof(char), strlen(RGBDS_OBJECT_VERSION_STRING),
|
||||
pObjfile) != strlen(RGBDS_OBJECT_VERSION_STRING)) {
|
||||
pObjfile) != strlen(RGBDS_OBJECT_VERSION_STRING)) {
|
||||
errx(1, "%s: Read error.", tzObjectfile);
|
||||
}
|
||||
|
||||
tzHeader[strlen(RGBDS_OBJECT_VERSION_STRING)] = 0;
|
||||
|
||||
if (strncmp(tzHeader, RGBDS_OBJECT_VERSION_STRING,
|
||||
strlen(RGBDS_OBJECT_VERSION_STRING)) == 0) {
|
||||
strlen(RGBDS_OBJECT_VERSION_STRING)) == 0) {
|
||||
obj_ReadRGB(pObjfile, tzObjectfile);
|
||||
} else {
|
||||
for (int32_t i = 0; i < strlen(RGBDS_OBJECT_VERSION_STRING); i++)
|
||||
int32_t i;
|
||||
|
||||
for (i = 0; i < strlen(RGBDS_OBJECT_VERSION_STRING); i++)
|
||||
if (!isprint(tzHeader[i]))
|
||||
tzHeader[i] = '?';
|
||||
|
||||
errx(1, "%s: Invalid file or object file version [%s]",
|
||||
tzObjectfile, tzHeader);
|
||||
tzObjectfile, tzHeader);
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
obj_Readfile(char *tzObjectfile)
|
||||
void obj_Readfile(char *tzObjectfile)
|
||||
{
|
||||
FILE *pObjfile;
|
||||
|
||||
@@ -372,17 +348,16 @@ obj_Readfile(char *tzObjectfile)
|
||||
oReadLib = 0;
|
||||
|
||||
pObjfile = fopen(tzObjectfile, "rb");
|
||||
if (pObjfile == NULL) {
|
||||
if (pObjfile == NULL)
|
||||
err(1, "Unable to open object '%s'", tzObjectfile);
|
||||
}
|
||||
|
||||
obj_ReadOpenFile(pObjfile, tzObjectfile);
|
||||
fclose(pObjfile);
|
||||
|
||||
oReadLib = 0;
|
||||
}
|
||||
|
||||
int32_t
|
||||
file_Length(FILE * f)
|
||||
int32_t file_Length(FILE *f)
|
||||
{
|
||||
uint32_t r, p;
|
||||
|
||||
@@ -391,5 +366,5 @@ file_Length(FILE * f)
|
||||
r = ftell(f);
|
||||
fseek(f, p, SEEK_SET);
|
||||
|
||||
return (r);
|
||||
return r;
|
||||
}
|
||||
|
||||
@@ -4,20 +4,20 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "extern/err.h"
|
||||
|
||||
#include "link/mylink.h"
|
||||
#include "link/mapfile.h"
|
||||
#include "link/main.h"
|
||||
#include "link/assign.h"
|
||||
|
||||
char *tzOutname;
|
||||
char *tzOverlayname = NULL;
|
||||
char *tzOverlayname;
|
||||
|
||||
int32_t MaxOverlayBank;
|
||||
|
||||
void
|
||||
writehome(FILE * f, FILE * f_overlay)
|
||||
void writehome(FILE *f, FILE *f_overlay)
|
||||
{
|
||||
struct sSection *pSect;
|
||||
const struct sSection *pSect;
|
||||
uint8_t *mem;
|
||||
|
||||
mem = malloc(MaxAvail[BANK_ROM0]);
|
||||
@@ -39,7 +39,7 @@ writehome(FILE * f, FILE * f_overlay)
|
||||
while (pSect) {
|
||||
if (pSect->Type == SECT_ROM0) {
|
||||
memcpy(mem + pSect->nOrg, pSect->pData,
|
||||
pSect->nByteSize);
|
||||
pSect->nByteSize);
|
||||
MapfileWriteSection(pSect);
|
||||
}
|
||||
pSect = pSect->pNext;
|
||||
@@ -51,10 +51,9 @@ writehome(FILE * f, FILE * f_overlay)
|
||||
free(mem);
|
||||
}
|
||||
|
||||
void
|
||||
writebank(FILE * f, FILE * f_overlay, int32_t bank)
|
||||
void writebank(FILE *f, FILE *f_overlay, int32_t bank)
|
||||
{
|
||||
struct sSection *pSect;
|
||||
const struct sSection *pSect;
|
||||
uint8_t *mem;
|
||||
|
||||
mem = malloc(MaxAvail[bank]);
|
||||
@@ -62,11 +61,9 @@ writebank(FILE * f, FILE * f_overlay, int32_t bank)
|
||||
return;
|
||||
|
||||
if (f_overlay != NULL && bank <= MaxOverlayBank) {
|
||||
fseek(f_overlay, bank*0x4000, SEEK_SET);
|
||||
if (fread(mem, 1, MaxAvail[bank], f_overlay) !=
|
||||
MaxAvail[bank]) {
|
||||
fseek(f_overlay, bank * 0x4000, SEEK_SET);
|
||||
if (fread(mem, 1, MaxAvail[bank], f_overlay) != MaxAvail[bank])
|
||||
warnx("Failed to read data from overlay file.");
|
||||
}
|
||||
} else {
|
||||
memset(mem, fillchar, MaxAvail[bank]);
|
||||
}
|
||||
@@ -76,7 +73,7 @@ writebank(FILE * f, FILE * f_overlay, int32_t bank)
|
||||
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;
|
||||
@@ -88,43 +85,49 @@ writebank(FILE * f, FILE * f_overlay, int32_t bank)
|
||||
free(mem);
|
||||
}
|
||||
|
||||
void
|
||||
out_Setname(char *tzOutputfile)
|
||||
void out_Setname(char *tzOutputfile)
|
||||
{
|
||||
tzOutname = tzOutputfile;
|
||||
}
|
||||
|
||||
void
|
||||
out_SetOverlayname(char *tzOverlayfile)
|
||||
void out_SetOverlayname(char *tzOverlayfile)
|
||||
{
|
||||
tzOverlayname = tzOverlayfile;
|
||||
}
|
||||
|
||||
|
||||
void
|
||||
Output(void)
|
||||
void Output(void)
|
||||
{
|
||||
int32_t i;
|
||||
FILE *f;
|
||||
FILE *f_overlay = NULL;
|
||||
|
||||
if ((f = fopen(tzOutname, "wb"))) {
|
||||
/*
|
||||
* Apply overlay
|
||||
*/
|
||||
|
||||
f = fopen(tzOutname, "wb");
|
||||
|
||||
if (f != NULL) {
|
||||
if (tzOverlayname) {
|
||||
f_overlay = fopen(tzOverlayname, "rb");
|
||||
|
||||
if (!f_overlay) {
|
||||
errx(1, "Failed to open overlay file %s\n", tzOverlayname);
|
||||
errx(1, "Failed to open overlay file %s\n",
|
||||
tzOverlayname);
|
||||
}
|
||||
|
||||
fseek(f_overlay, 0, SEEK_END);
|
||||
if (ftell(f_overlay) % 0x4000 != 0) {
|
||||
|
||||
if (ftell(f_overlay) % 0x4000 != 0)
|
||||
errx(1, "Overlay file must be aligned to 0x4000 bytes.");
|
||||
}
|
||||
|
||||
MaxOverlayBank = (ftell(f_overlay) / 0x4000) - 1;
|
||||
if (MaxOverlayBank < 1) {
|
||||
|
||||
if (MaxOverlayBank < 1)
|
||||
errx(1, "Overlay file must be at least 0x8000 bytes.");
|
||||
}
|
||||
if (MaxOverlayBank > MaxBankUsed) {
|
||||
|
||||
if (MaxOverlayBank > MaxBankUsed)
|
||||
MaxBankUsed = MaxOverlayBank;
|
||||
}
|
||||
}
|
||||
|
||||
writehome(f, f_overlay);
|
||||
@@ -133,18 +136,22 @@ Output(void)
|
||||
|
||||
fclose(f);
|
||||
|
||||
if (tzOverlayname) {
|
||||
if (tzOverlayname)
|
||||
fclose(f_overlay);
|
||||
}
|
||||
}
|
||||
|
||||
/*
|
||||
* Add regular sections
|
||||
*/
|
||||
|
||||
for (i = BANK_WRAM0; i < MAXBANKS; i++) {
|
||||
struct sSection *pSect;
|
||||
const struct sSection *pSect;
|
||||
|
||||
MapfileInitBank(i);
|
||||
pSect = pSections;
|
||||
while (pSect) {
|
||||
if (pSect->nBank == i) {
|
||||
if (pSect->nBank == i)
|
||||
MapfileWriteSection(pSect);
|
||||
}
|
||||
pSect = pSect->pNext;
|
||||
}
|
||||
MapfileCloseBank(area_Avail(i));
|
||||
|
||||
@@ -19,6 +19,7 @@
|
||||
#include <stdio.h>
|
||||
|
||||
#include "extern/err.h"
|
||||
|
||||
#include "link/script.h"
|
||||
|
||||
int yylex();
|
||||
@@ -27,7 +28,10 @@ void yyerror(char *);
|
||||
extern int yylineno;
|
||||
%}
|
||||
|
||||
%union { int32_t i; char s[512]; }
|
||||
%union {
|
||||
int32_t i;
|
||||
char s[512];
|
||||
}
|
||||
|
||||
%token<i> INTEGER
|
||||
%token<s> STRING
|
||||
@@ -49,55 +53,65 @@ extern int yylineno;
|
||||
lines:
|
||||
/* empty */
|
||||
| lines line NEWLINE
|
||||
;
|
||||
;
|
||||
|
||||
line:
|
||||
/* empty */
|
||||
| statement
|
||||
;
|
||||
;
|
||||
|
||||
statement:
|
||||
/* Statements to set the current section */
|
||||
SECTION_NONBANKED {
|
||||
SECTION_NONBANKED
|
||||
{
|
||||
script_SetCurrentSectionType($1, 0);
|
||||
}
|
||||
| SECTION_NONBANKED INTEGER {
|
||||
| SECTION_NONBANKED INTEGER
|
||||
{
|
||||
script_fatalerror("Trying to assign a bank to a non-banked section.\n");
|
||||
}
|
||||
|
||||
| SECTION_BANKED {
|
||||
| SECTION_BANKED
|
||||
{
|
||||
script_fatalerror("Banked section without assigned bank.\n");
|
||||
}
|
||||
| SECTION_BANKED INTEGER {
|
||||
| SECTION_BANKED INTEGER
|
||||
{
|
||||
script_SetCurrentSectionType($1, $2);
|
||||
}
|
||||
|
||||
/* Commands to adjust the address inside the current section */
|
||||
| COMMAND_ALIGN INTEGER {
|
||||
| COMMAND_ALIGN INTEGER
|
||||
{
|
||||
script_SetAlignment($2);
|
||||
}
|
||||
| COMMAND_ALIGN {
|
||||
| COMMAND_ALIGN
|
||||
{
|
||||
script_fatalerror("ALIGN keyword needs an argument.\n");
|
||||
}
|
||||
| COMMAND_ORG INTEGER {
|
||||
| COMMAND_ORG INTEGER
|
||||
{
|
||||
script_SetAddress($2);
|
||||
}
|
||||
| COMMAND_ORG {
|
||||
| COMMAND_ORG
|
||||
{
|
||||
script_fatalerror("ORG keyword needs an argument.\n");
|
||||
}
|
||||
|
||||
/* Section name */
|
||||
| STRING {
|
||||
| STRING
|
||||
{
|
||||
script_OutputSection($1);
|
||||
}
|
||||
|
||||
/* Include file */
|
||||
| COMMAND_INCLUDE STRING {
|
||||
| COMMAND_INCLUDE STRING
|
||||
{
|
||||
script_IncludeFile($2);
|
||||
}
|
||||
|
||||
/* End */
|
||||
;
|
||||
;
|
||||
|
||||
%%
|
||||
|
||||
|
||||
133
src/link/patch.c
133
src/link/patch.c
@@ -4,87 +4,83 @@
|
||||
#include <string.h>
|
||||
|
||||
#include "extern/err.h"
|
||||
|
||||
#include "link/assign.h"
|
||||
#include "link/main.h"
|
||||
#include "link/mylink.h"
|
||||
#include "link/symbol.h"
|
||||
#include "link/main.h"
|
||||
|
||||
struct sSection *pCurrentSection;
|
||||
int32_t rpnstack[256];
|
||||
int32_t rpnp;
|
||||
static struct sSection *pCurrentSection;
|
||||
static int32_t rpnstack[256];
|
||||
static int32_t rpnp;
|
||||
int32_t nPC;
|
||||
|
||||
void
|
||||
rpnpush(int32_t i)
|
||||
static void rpnpush(int32_t i)
|
||||
{
|
||||
rpnstack[rpnp++] = i;
|
||||
rpnstack[rpnp] = i;
|
||||
rpnp++;
|
||||
}
|
||||
|
||||
int32_t
|
||||
rpnpop(void)
|
||||
static int32_t rpnpop(void)
|
||||
{
|
||||
return (rpnstack[--rpnp]);
|
||||
rpnp--;
|
||||
return rpnstack[rpnp];
|
||||
}
|
||||
|
||||
int32_t
|
||||
getsymvalue(int32_t symid)
|
||||
int32_t getsymvalue(int32_t symid)
|
||||
{
|
||||
switch (pCurrentSection->tSymbols[symid]->Type) {
|
||||
case SYM_IMPORT:
|
||||
return (sym_GetValue(pCurrentSection->tSymbols[symid]->pzName));
|
||||
break;
|
||||
case SYM_EXPORT:
|
||||
case SYM_LOCAL:
|
||||
{
|
||||
if (strcmp
|
||||
(pCurrentSection->tSymbols[symid]->pzName,
|
||||
"@") == 0) {
|
||||
return (nPC);
|
||||
} else
|
||||
return (pCurrentSection->tSymbols[symid]->
|
||||
nOffset +
|
||||
pCurrentSection->tSymbols[symid]->
|
||||
pSection->nOrg);
|
||||
}
|
||||
default:
|
||||
break;
|
||||
}
|
||||
errx(1, "*INTERNAL* UNKNOWN SYMBOL TYPE");
|
||||
}
|
||||
const struct sSymbol *tSymbol = pCurrentSection->tSymbols[symid];
|
||||
|
||||
int32_t
|
||||
getsymbank(int32_t symid)
|
||||
{
|
||||
int32_t nBank;
|
||||
|
||||
switch (pCurrentSection->tSymbols[symid]->Type) {
|
||||
switch (tSymbol->Type) {
|
||||
case SYM_IMPORT:
|
||||
nBank = sym_GetBank(pCurrentSection->tSymbols[symid]->pzName);
|
||||
return sym_GetValue(tSymbol->pzName);
|
||||
|
||||
case SYM_EXPORT:
|
||||
case SYM_LOCAL:
|
||||
if (strcmp(tSymbol->pzName, "@") == 0)
|
||||
return nPC;
|
||||
|
||||
return tSymbol->nOffset + tSymbol->pSection->nOrg;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
errx(1, "%s: Unknown symbol type", __func__);
|
||||
}
|
||||
|
||||
int32_t getsymbank(int32_t symid)
|
||||
{
|
||||
int32_t n;
|
||||
const struct sSymbol *tSymbol = pCurrentSection->tSymbols[symid];
|
||||
|
||||
switch (tSymbol->Type) {
|
||||
case SYM_IMPORT:
|
||||
n = sym_GetBank(tSymbol->pzName);
|
||||
break;
|
||||
case SYM_EXPORT:
|
||||
case SYM_LOCAL:
|
||||
nBank = pCurrentSection->tSymbols[symid]->pSection->nBank;
|
||||
n = tSymbol->pSection->nBank;
|
||||
break;
|
||||
default:
|
||||
errx(1, "*INTERNAL* UNKNOWN SYMBOL TYPE");
|
||||
errx(1, "%s: Unknown symbol type", __func__);
|
||||
}
|
||||
|
||||
if (nBank == BANK_WRAM0 || nBank == BANK_ROM0 || nBank == BANK_OAM ||
|
||||
nBank == BANK_HRAM) {
|
||||
if ((n == BANK_WRAM0) || (n == BANK_ROM0) || (n == BANK_OAM) ||
|
||||
(n == BANK_HRAM)) {
|
||||
return 0;
|
||||
} else if (nBank >= BANK_WRAMX && nBank < (BANK_WRAMX + BANK_COUNT_WRAMX)) {
|
||||
return nBank - BANK_WRAMX + 1;
|
||||
} else if (nBank >= BANK_VRAM && nBank < (BANK_VRAM + BANK_COUNT_VRAM)) {
|
||||
return nBank - BANK_VRAM;
|
||||
} else if (nBank >= BANK_SRAM && nBank < (BANK_SRAM + BANK_COUNT_SRAM)) {
|
||||
return nBank - BANK_SRAM;
|
||||
} else if ((n >= BANK_WRAMX) && (n < (BANK_WRAMX + BANK_COUNT_WRAMX))) {
|
||||
return n - BANK_WRAMX + 1;
|
||||
} else if ((n >= BANK_VRAM) && (n < (BANK_VRAM + BANK_COUNT_VRAM))) {
|
||||
return n - BANK_VRAM;
|
||||
} else if ((n >= BANK_SRAM) && (n < (BANK_SRAM + BANK_COUNT_SRAM))) {
|
||||
return n - BANK_SRAM;
|
||||
}
|
||||
|
||||
return nBank;
|
||||
return n;
|
||||
}
|
||||
|
||||
int32_t
|
||||
calcrpn(struct sPatch * pPatch)
|
||||
int32_t calcrpn(struct sPatch *pPatch)
|
||||
{
|
||||
int32_t t, size;
|
||||
uint8_t *rpn;
|
||||
@@ -175,8 +171,8 @@ calcrpn(struct sPatch * pPatch)
|
||||
rpnpush(t & 0xFF);
|
||||
if (t < 0 || (t > 0xFF && t < 0xFF00) || t > 0xFFFF) {
|
||||
errx(1,
|
||||
"%s(%ld) : Value must be in the HRAM area",
|
||||
pPatch->pzFilename, pPatch->nLineNo);
|
||||
"%s(%ld) : Value must be in the HRAM area",
|
||||
pPatch->pzFilename, pPatch->nLineNo);
|
||||
}
|
||||
break;
|
||||
case RPN_CONST:
|
||||
@@ -209,11 +205,10 @@ calcrpn(struct sPatch * pPatch)
|
||||
break;
|
||||
}
|
||||
}
|
||||
return (rpnpop());
|
||||
return rpnpop();
|
||||
}
|
||||
|
||||
void
|
||||
Patch(void)
|
||||
void Patch(void)
|
||||
{
|
||||
struct sSection *pSect;
|
||||
|
||||
@@ -233,12 +228,12 @@ Patch(void)
|
||||
if (t >= -128 && t <= 255) {
|
||||
t &= 0xFF;
|
||||
pSect->pData[pPatch->nOffset] =
|
||||
(uint8_t) t;
|
||||
(uint8_t)t;
|
||||
} else {
|
||||
errx(1,
|
||||
"%s(%ld) : Value must be 8-bit",
|
||||
pPatch->pzFilename,
|
||||
pPatch->nLineNo);
|
||||
"%s(%ld) : Value must be 8-bit",
|
||||
pPatch->pzFilename,
|
||||
pPatch->nLineNo);
|
||||
}
|
||||
break;
|
||||
case PATCH_WORD_L:
|
||||
@@ -250,19 +245,19 @@ Patch(void)
|
||||
(t >> 8) & 0xFF;
|
||||
} else {
|
||||
errx(1,
|
||||
"%s(%ld) : Value must be 16-bit",
|
||||
pPatch->pzFilename,
|
||||
pPatch->nLineNo);
|
||||
"%s(%ld) : Value must be 16-bit",
|
||||
pPatch->pzFilename,
|
||||
pPatch->nLineNo);
|
||||
}
|
||||
break;
|
||||
case PATCH_LONG_L:
|
||||
pSect->pData[pPatch->nOffset + 0] = t & 0xFF;
|
||||
pSect->pData[pPatch->nOffset + 1] =
|
||||
(t >> 8) & 0xFF;
|
||||
(t >> 8) & 0xFF;
|
||||
pSect->pData[pPatch->nOffset + 2] =
|
||||
(t >> 16) & 0xFF;
|
||||
(t >> 16) & 0xFF;
|
||||
pSect->pData[pPatch->nOffset + 3] =
|
||||
(t >> 24) & 0xFF;
|
||||
(t >> 24) & 0xFF;
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -34,15 +34,15 @@ static int32_t current_real_bank = -1; /* bank as seen by the GB */
|
||||
void script_InitSections(void)
|
||||
{
|
||||
int32_t i;
|
||||
|
||||
for (i = 0; i < MAXBANKS; i++) {
|
||||
if (i == BANK_ROM0) {
|
||||
/* ROM0 bank */
|
||||
bank[i].address = 0x0000;
|
||||
if (options & OPT_TINY) {
|
||||
if (options & OPT_TINY)
|
||||
bank[i].top_address = 0x8000;
|
||||
} else {
|
||||
else
|
||||
bank[i].top_address = 0x4000;
|
||||
}
|
||||
bank[i].type = SECT_ROM0;
|
||||
} else if (i >= BANK_ROMX && i < BANK_ROMX + BANK_COUNT_ROMX) {
|
||||
/* Swappable ROM bank */
|
||||
@@ -52,11 +52,10 @@ void script_InitSections(void)
|
||||
} else if (i == BANK_WRAM0) {
|
||||
/* WRAM */
|
||||
bank[i].address = 0xC000;
|
||||
if (options & OPT_CONTWRAM) {
|
||||
if (options & OPT_CONTWRAM)
|
||||
bank[i].top_address = 0xE000;
|
||||
} else {
|
||||
else
|
||||
bank[i].top_address = 0xD000;
|
||||
}
|
||||
bank[i].type = SECT_WRAM0;
|
||||
} else if (i >= BANK_SRAM && i < BANK_SRAM + BANK_COUNT_SRAM) {
|
||||
/* Swappable SRAM bank */
|
||||
@@ -105,14 +104,18 @@ void script_SetCurrentSectionType(const char *type, uint32_t bank)
|
||||
} else if (strcmp(type, "ROMX") == 0) {
|
||||
if (bank == 0)
|
||||
errx(1, "ROMX index can't be 0.\n");
|
||||
if (bank > BANK_COUNT_ROMX)
|
||||
errx(1, "ROMX index too big (%d > %d).\n", bank, BANK_COUNT_ROMX);
|
||||
if (bank > BANK_COUNT_ROMX) {
|
||||
errx(1, "ROMX index too big (%d > %d).\n", bank,
|
||||
BANK_COUNT_ROMX);
|
||||
}
|
||||
current_bank = BANK_ROMX + bank - 1;
|
||||
current_real_bank = bank;
|
||||
return;
|
||||
} else if (strcmp(type, "VRAM") == 0) {
|
||||
if (bank >= BANK_COUNT_VRAM)
|
||||
errx(1, "VRAM index too big (%d >= %d).\n", bank, BANK_COUNT_VRAM);
|
||||
if (bank >= BANK_COUNT_VRAM) {
|
||||
errx(1, "VRAM index too big (%d >= %d).\n", bank,
|
||||
BANK_COUNT_VRAM);
|
||||
}
|
||||
current_bank = BANK_VRAM + bank;
|
||||
current_real_bank = bank;
|
||||
return;
|
||||
@@ -125,14 +128,18 @@ void script_SetCurrentSectionType(const char *type, uint32_t bank)
|
||||
} else if (strcmp(type, "WRAMX") == 0) {
|
||||
if (bank == 0)
|
||||
errx(1, "WRAMX index can't be 0.\n");
|
||||
if (bank > BANK_COUNT_WRAMX)
|
||||
errx(1, "WRAMX index too big (%d > %d).\n", bank, BANK_COUNT_WRAMX);
|
||||
if (bank > BANK_COUNT_WRAMX) {
|
||||
errx(1, "WRAMX index too big (%d > %d).\n", bank,
|
||||
BANK_COUNT_WRAMX);
|
||||
}
|
||||
current_bank = BANK_WRAMX + bank - 1;
|
||||
current_real_bank = bank - 1;
|
||||
return;
|
||||
} else if (strcmp(type, "SRAM") == 0) {
|
||||
if (bank >= BANK_COUNT_SRAM)
|
||||
errx(1, "SRAM index too big (%d >= %d).\n", bank, BANK_COUNT_SRAM);
|
||||
if (bank >= BANK_COUNT_SRAM) {
|
||||
errx(1, "SRAM index too big (%d >= %d).\n", bank,
|
||||
BANK_COUNT_SRAM);
|
||||
}
|
||||
current_bank = BANK_SRAM + bank;
|
||||
current_real_bank = bank;
|
||||
return;
|
||||
@@ -155,14 +162,13 @@ void script_SetCurrentSectionType(const char *type, uint32_t bank)
|
||||
|
||||
void script_SetAddress(uint32_t addr)
|
||||
{
|
||||
if (current_bank == -1) {
|
||||
if (current_bank == -1)
|
||||
errx(1, "Trying to set an address without assigned bank\n");
|
||||
}
|
||||
|
||||
/* Make sure that we don't go back. */
|
||||
if (bank[current_bank].address > addr) {
|
||||
errx(1, "Trying to go to a previous address (0x%04X to 0x%04X)\n",
|
||||
bank[current_bank].address, addr);
|
||||
bank[current_bank].address, addr);
|
||||
}
|
||||
|
||||
bank[current_bank].address = addr;
|
||||
@@ -170,19 +176,18 @@ void script_SetAddress(uint32_t addr)
|
||||
/* Make sure we don't overflow */
|
||||
if (bank[current_bank].address >= bank[current_bank].top_address) {
|
||||
errx(1, "Bank overflowed (0x%04X >= 0x%04X)\n",
|
||||
bank[current_bank].address, bank[current_bank].top_address);
|
||||
bank[current_bank].address,
|
||||
bank[current_bank].top_address);
|
||||
}
|
||||
}
|
||||
|
||||
void script_SetAlignment(uint32_t alignment)
|
||||
{
|
||||
if (current_bank == -1) {
|
||||
if (current_bank == -1)
|
||||
errx(1, "Trying to set an alignment without assigned bank\n");
|
||||
}
|
||||
|
||||
if (alignment > 15) {
|
||||
if (alignment > 15)
|
||||
errx(1, "Trying to set an alignment too big: %d\n", alignment);
|
||||
}
|
||||
|
||||
uint32_t size = 1 << alignment;
|
||||
uint32_t mask = size - 1;
|
||||
@@ -195,25 +200,29 @@ void script_SetAlignment(uint32_t alignment)
|
||||
/* Make sure we don't overflow */
|
||||
if (bank[current_bank].address >= bank[current_bank].top_address) {
|
||||
errx(1, "Bank overflowed (0x%04X >= 0x%04X)\n",
|
||||
bank[current_bank].address, bank[current_bank].top_address);
|
||||
bank[current_bank].address,
|
||||
bank[current_bank].top_address);
|
||||
}
|
||||
}
|
||||
|
||||
void script_OutputSection(const char *section_name)
|
||||
{
|
||||
if (current_bank == -1) {
|
||||
errx(1, "Trying to place section \"%s\" without assigned bank\n", section_name);
|
||||
errx(1, "Trying to place section \"%s\" without assigned bank\n",
|
||||
section_name);
|
||||
}
|
||||
|
||||
if (!IsSectionSameTypeBankAndFloating(section_name, bank[current_bank].type,
|
||||
current_real_bank)) {
|
||||
if (!IsSectionSameTypeBankAndFloating(section_name,
|
||||
bank[current_bank].type,
|
||||
current_real_bank)) {
|
||||
errx(1, "Different attributes for \"%s\" in source and linkerscript\n",
|
||||
section_name);
|
||||
section_name);
|
||||
}
|
||||
|
||||
/* Move section to its place. */
|
||||
bank[current_bank].address +=
|
||||
AssignSectionAddressAndBankByName(section_name,
|
||||
bank[current_bank].address, current_real_bank);
|
||||
bank[current_bank].address,
|
||||
current_real_bank);
|
||||
}
|
||||
|
||||
|
||||
@@ -16,73 +16,70 @@ struct ISymbol {
|
||||
char *pzName;
|
||||
int32_t nValue;
|
||||
int32_t nBank; /* -1 = constant */
|
||||
char tzObjFileName[_MAX_PATH + 1]; /* Object file where the symbol was defined. */
|
||||
char tzFileName[_MAX_PATH + 1]; /* Source file where the symbol was defined. */
|
||||
uint32_t nFileLine; /* Line where the symbol was defined. */
|
||||
/* Object file where the symbol was defined. */
|
||||
char tzObjFileName[_MAX_PATH + 1];
|
||||
/* Source file where the symbol was defined. */
|
||||
char tzFileName[_MAX_PATH + 1];
|
||||
/* Line where the symbol was defined. */
|
||||
uint32_t nFileLine;
|
||||
struct ISymbol *pNext;
|
||||
};
|
||||
|
||||
struct ISymbol *tHash[HASHSIZE];
|
||||
|
||||
int32_t
|
||||
calchash(char *s)
|
||||
int32_t calchash(char *s)
|
||||
{
|
||||
int32_t r = 0;
|
||||
|
||||
while (*s)
|
||||
r += *s++;
|
||||
|
||||
return (r % HASHSIZE);
|
||||
return r % HASHSIZE;
|
||||
}
|
||||
|
||||
void
|
||||
sym_Init(void)
|
||||
void sym_Init(void)
|
||||
{
|
||||
int32_t i;
|
||||
|
||||
for (i = 0; i < HASHSIZE; i += 1)
|
||||
tHash[i] = NULL;
|
||||
}
|
||||
|
||||
int32_t
|
||||
sym_GetValue(char *tzName)
|
||||
int32_t sym_GetValue(char *tzName)
|
||||
{
|
||||
if (strcmp(tzName, "@") == 0) {
|
||||
return (nPC);
|
||||
} else {
|
||||
struct ISymbol **ppSym;
|
||||
if (strcmp(tzName, "@") == 0)
|
||||
return nPC;
|
||||
|
||||
ppSym = &(tHash[calchash(tzName)]);
|
||||
while (*ppSym) {
|
||||
if (strcmp(tzName, (*ppSym)->pzName)) {
|
||||
ppSym = &((*ppSym)->pNext);
|
||||
} else {
|
||||
return ((*ppSym)->nValue);
|
||||
}
|
||||
}
|
||||
|
||||
errx(1, "Unknown symbol '%s'", tzName);
|
||||
}
|
||||
}
|
||||
|
||||
int32_t
|
||||
sym_GetBank(char *tzName)
|
||||
{
|
||||
struct ISymbol **ppSym;
|
||||
|
||||
ppSym = &(tHash[calchash(tzName)]);
|
||||
while (*ppSym) {
|
||||
if (strcmp(tzName, (*ppSym)->pzName)) {
|
||||
if (strcmp(tzName, (*ppSym)->pzName))
|
||||
ppSym = &((*ppSym)->pNext);
|
||||
} else {
|
||||
return ((*ppSym)->nBank);
|
||||
}
|
||||
else
|
||||
return ((*ppSym)->nValue);
|
||||
}
|
||||
|
||||
errx(1, "Unknown symbol '%s'", tzName);
|
||||
}
|
||||
|
||||
void
|
||||
sym_CreateSymbol(char *tzName, int32_t nValue, int32_t nBank, char *tzObjFileName,
|
||||
char *tzFileName, uint32_t nFileLine)
|
||||
int32_t sym_GetBank(char *tzName)
|
||||
{
|
||||
struct ISymbol **ppSym;
|
||||
|
||||
ppSym = &(tHash[calchash(tzName)]);
|
||||
while (*ppSym) {
|
||||
if (strcmp(tzName, (*ppSym)->pzName))
|
||||
ppSym = &((*ppSym)->pNext);
|
||||
else
|
||||
return ((*ppSym)->nBank);
|
||||
}
|
||||
|
||||
errx(1, "Unknown symbol '%s'", tzName);
|
||||
}
|
||||
|
||||
void sym_CreateSymbol(char *tzName, int32_t nValue, int32_t nBank,
|
||||
char *tzObjFileName, char *tzFileName, uint32_t nFileLine)
|
||||
{
|
||||
if (strcmp(tzName, "@") == 0)
|
||||
return;
|
||||
@@ -99,14 +96,18 @@ sym_CreateSymbol(char *tzName, int32_t nValue, int32_t nBank, char *tzObjFileNam
|
||||
return;
|
||||
|
||||
errx(1, "'%s' in both %s : %s(%d) and %s : %s(%d)",
|
||||
tzName, tzObjFileName, tzFileName, nFileLine,
|
||||
(*ppSym)->tzObjFileName,
|
||||
(*ppSym)->tzFileName, (*ppSym)->nFileLine);
|
||||
tzName, tzObjFileName, tzFileName, nFileLine,
|
||||
(*ppSym)->tzObjFileName,
|
||||
(*ppSym)->tzFileName, (*ppSym)->nFileLine);
|
||||
}
|
||||
}
|
||||
|
||||
if ((*ppSym = malloc(sizeof **ppSym))) {
|
||||
if (((*ppSym)->pzName = malloc(strlen(tzName) + 1))) {
|
||||
*ppSym = malloc(sizeof **ppSym);
|
||||
|
||||
if (*ppSym != NULL) {
|
||||
(*ppSym)->pzName = malloc(strlen(tzName) + 1);
|
||||
|
||||
if ((*ppSym)->pzName != NULL) {
|
||||
strcpy((*ppSym)->pzName, tzName);
|
||||
(*ppSym)->nValue = nValue;
|
||||
(*ppSym)->nBank = nBank;
|
||||
|
||||
Reference in New Issue
Block a user