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