diff --git a/include/asm/output.h b/include/asm/output.h index 2afbccc5..fab83e36 100644 --- a/include/asm/output.h +++ b/include/asm/output.h @@ -10,6 +10,7 @@ struct Section { ULONG nPC; ULONG nOrg; ULONG nBank; + ULONG nAlign; struct Section *pNext; struct Patch *pPatches; struct Charmap *charmap; @@ -20,6 +21,7 @@ void out_PrepPass2(void); void out_SetFileName(char *s); void out_NewSection(char *pzName, ULONG secttype); void out_NewAbsSection(char *pzName, ULONG secttype, SLONG org, SLONG bank); +void out_NewAlignedSection(char *pzName, ULONG secttype, SLONG alignment, SLONG bank); void out_AbsByte(int b); void out_AbsByteGroup(char *s, int length); void out_RelByte(struct Expression * expr); diff --git a/include/link/mylink.h b/include/link/mylink.h index 707d5fbf..9ce6e4e4 100644 --- a/include/link/mylink.h +++ b/include/link/mylink.h @@ -63,8 +63,10 @@ enum eSectionType { struct sSection { SLONG nBank; SLONG nOrg; + SLONG nAlign; BBOOL oAssigned; + char *pzName; SLONG nByteSize; enum eSectionType Type; UBYTE *pData; diff --git a/src/asm/asmy.y b/src/asm/asmy.y index 6264f74e..c54d41d6 100644 --- a/src/asm/asmy.y +++ b/src/asm/asmy.y @@ -460,7 +460,7 @@ void if_skip_to_endc( void ) %left T_OP_MUL T_OP_DIV T_OP_MOD %left T_OP_NOT %left T_OP_DEF -%left T_OP_BANK +%left T_OP_BANK T_OP_ALIGN %left T_OP_SIN %left T_OP_COS %left T_OP_TAN @@ -1113,6 +1113,10 @@ section: else yyerror("Address $%x not 16-bit", $6); } + | T_POP_SECTION string ',' sectiontype ',' T_OP_ALIGN '[' const ']' + { + out_NewAlignedSection($2, $4, $8, -1); + } | T_POP_SECTION string ',' sectiontype ',' T_OP_BANK '[' const ']' { bankrangecheck($2, $4, -1, $8); @@ -1124,6 +1128,14 @@ section: } bankrangecheck($2, $4, $6, $11); } + | T_POP_SECTION string ',' sectiontype ',' T_OP_ALIGN '[' const ']' ',' T_OP_BANK '[' const ']' + { + out_NewAlignedSection($2, $4, $8, $13); + } + | T_POP_SECTION string ',' sectiontype ',' T_OP_BANK '[' const ']' ',' T_OP_ALIGN '[' const ']' + { + out_NewAlignedSection($2, $4, $13, $8); + } ; sectiontype: diff --git a/src/asm/globlex.c b/src/asm/globlex.c index 9f9523a8..dd379277 100644 --- a/src/asm/globlex.c +++ b/src/asm/globlex.c @@ -267,6 +267,7 @@ struct sLexInitString staticstrings[] = { {"def", T_OP_DEF}, {"bank", T_OP_BANK}, + {"align", T_OP_ALIGN}, {"round", T_OP_ROUND}, {"ceil", T_OP_CEIL}, diff --git a/src/asm/output.c b/src/asm/output.c index d4147a1b..92340fa8 100644 --- a/src/asm/output.c +++ b/src/asm/output.c @@ -201,17 +201,18 @@ writepatch(struct Patch * pPatch, FILE * f) void writesection(struct Section * pSect, FILE * f) { - //printf("SECTION: %s, ID: %d\n", pSect->pzName, getsectid(pSect)); - + fputstring(pSect->pzName, f); // RGB3 addition fputlong(pSect->nPC, f); fputc(pSect->nType, f); fputlong(pSect->nOrg, f); //RGB1 addition - fputlong(pSect->nBank, f); + fputlong(pSect->nBank, f); //RGB1 addition + + fputlong(pSect->nAlign, f); // RGB3 addition - if ((pSect->nType == SECT_ROM0) + if ((pSect->nType == SECT_ROM0) || (pSect->nType == SECT_ROMX)) { struct Patch *pPatch; @@ -490,7 +491,7 @@ out_WriteObject(void) struct PatchSymbol *pSym; struct Section *pSect; - fwrite("RGB2", 1, 4, f); + fwrite("RGB3", 1, 4, f); fputlong(countsymbols(), f); fputlong(countsections(), f); @@ -546,7 +547,7 @@ out_SetFileName(char *s) * Find a section by name and type. If it doesn't exist, create it */ struct Section * -out_FindSection(char *pzName, ULONG secttype, SLONG org, SLONG bank) +out_FindSection(char *pzName, ULONG secttype, SLONG org, SLONG bank, SLONG alignment) { struct Section *pSect, **ppSect; @@ -557,7 +558,8 @@ out_FindSection(char *pzName, ULONG secttype, SLONG org, SLONG bank) if (strcmp(pzName, pSect->pzName) == 0) { if (secttype == pSect->nType && ((ULONG) org) == pSect->nOrg - && ((ULONG) bank) == pSect->nBank) { + && ((ULONG) bank) == pSect->nBank + && ((ULONG) alignment == pSect->nAlign)) { return (pSect); } else fatalerror @@ -574,6 +576,7 @@ out_FindSection(char *pzName, ULONG secttype, SLONG org, SLONG bank) pSect->nPC = 0; pSect->nOrg = org; pSect->nBank = bank; + pSect->nAlign = alignment; pSect->pNext = NULL; pSect->pPatches = NULL; pSect->charmap = NULL; @@ -610,7 +613,7 @@ out_SetCurrentSection(struct Section * pSect) void out_NewSection(char *pzName, ULONG secttype) { - out_SetCurrentSection(out_FindSection(pzName, secttype, -1, -1)); + out_SetCurrentSection(out_FindSection(pzName, secttype, -1, -1, 1)); } /* @@ -619,7 +622,19 @@ out_NewSection(char *pzName, ULONG secttype) void out_NewAbsSection(char *pzName, ULONG secttype, SLONG org, SLONG bank) { - out_SetCurrentSection(out_FindSection(pzName, secttype, org, bank)); + out_SetCurrentSection(out_FindSection(pzName, secttype, org, bank, 1)); +} + +/* + * Set the current section by name and type, using a given byte alignment + */ +void +out_NewAlignedSection(char *pzName, ULONG secttype, SLONG alignment, SLONG bank) +{ + if (alignment < 0 || alignment > 16) { + yyerror("Alignment must be between 0-16 bits."); + } + out_SetCurrentSection(out_FindSection(pzName, secttype, -1, bank, 1 << alignment)); } /* diff --git a/src/link/assign.c b/src/link/assign.c index e602ebd7..91192578 100644 --- a/src/link/assign.c +++ b/src/link/assign.c @@ -46,7 +46,7 @@ const struct sSectionAttributes SECT_ATTRIBUTES[] = { case SECT_WRAMX: DOMAXWBANK(y); break; \ case SECT_SRAM: DOMAXSBANK(y); break; \ case SECT_VRAM: DOMAXVBANK(y); break; \ - default: errx(1, "DOMAXBANK used with invalid parameters"); 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);} @@ -77,6 +77,40 @@ area_Avail(SLONG bank) return (r); } +SLONG +area_doAlloc(struct sFreeArea *pArea, SLONG org, SLONG size) +{ + 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); + } + } + } + } + + return -1; +} + SLONG area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size) { @@ -84,39 +118,11 @@ area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size) pArea = *ppArea; while (pArea) { - if (org >= pArea->nOrg - && (org + size - 1) <= (pArea->nOrg + pArea->nSize - 1)) { - if (org == pArea->nOrg) { - pArea->nOrg += size; - pArea->nSize -= size; - return 0; - } else { - if ((org + size - 1) == - (pArea->nOrg + pArea->nSize - 1)) { - pArea->nSize -= size; - return 0; - } 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 0; - } else { - err(1, NULL); - } - } - } + SLONG result = area_doAlloc(pArea, org, size); + if (result != -1) { + return result; } + ppArea = &(pArea->pNext); pArea = *ppArea; } @@ -141,38 +147,42 @@ area_AllocAbsAnyBank(SLONG org, SLONG size, enum eSectionType type) return -1; } -SLONG -area_Alloc(struct sFreeArea ** ppArea, SLONG size) -{ +SLONG +area_Alloc(struct sFreeArea ** ppArea, SLONG size, SLONG alignment) { struct sFreeArea *pArea; - + if (alignment < 1) { + alignment = 1; + } + pArea = *ppArea; while (pArea) { - if (size <= pArea->nSize) { - SLONG r; - - r = pArea->nOrg; - pArea->nOrg += size; - pArea->nSize -= size; - - return (r); + SLONG org = pArea->nOrg; + if (org % alignment) { + org += alignment; } + org -= org % alignment; + + SLONG result = area_doAlloc(pArea, org, size); + if (result != -1) { + return result; + } + ppArea = &(pArea->pNext); pArea = *ppArea; } - return (-1); + return -1; } SLONG -area_AllocAnyBank(SLONG size, enum eSectionType type) { +area_AllocAnyBank(SLONG size, SLONG alignment, enum eSectionType type) { ensureSectionTypeIsValid(type); SLONG startBank = SECT_ATTRIBUTES[type].bank; SLONG bankCount = SECT_ATTRIBUTES[type].bankCount; for (int i = 0; i < bankCount; i++) { - SLONG org = area_Alloc(&BankFree[startBank + i], size); + SLONG org = area_Alloc(&BankFree[startBank + i], size, alignment); if (org != -1) { return ((startBank + i) << 16) | org; } @@ -182,45 +192,27 @@ area_AllocAnyBank(SLONG size, enum eSectionType type) { } struct sSection * -FindLargestSection(enum eSectionType type) +FindLargestSection(enum eSectionType type, bool bankFixed) { struct sSection *pSection, *r = NULL; SLONG nLargest = 0; + SLONG nLargestAlignment = 0; pSection = pSections; while (pSection) { - if (pSection->oAssigned == 0 && pSection->Type == type) { - if (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; } } pSection = pSection->pNext; } + return r; } -void -AssignBankedSections(enum eSectionType type) -{ - ensureSectionTypeIsValid(type); - - struct sSection *pSection; - - while ((pSection = FindLargestSection(type))) { - SLONG org; - - if ((org = area_AllocAnyBank(pSection->nByteSize, type)) != -1) { - pSection->nOrg = org & 0xFFFF; - pSection->nBank = org >> 16; - pSection->oAssigned = 1; - DOMAXBANK(pSection->Type, pSection->nBank); - } else { - errx(1, "Unable to place %s section anywhere", - SECT_ATTRIBUTES[type].name); - } - } -} bool VerifyAndSetBank(struct sSection *pSection) @@ -237,6 +229,47 @@ VerifyAndSetBank(struct sSection *pSection) } } +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 { + errx(1, "Unable to load fixed %s section into bank $%02lX", + SECT_ATTRIBUTES[pSection->Type].name, pSection->nBank); + } + } +} + +void +AssignFloatingBankSections(enum eSectionType type) +{ + ensureSectionTypeIsValid(type); + + struct sSection *pSection; + + while ((pSection = FindLargestSection(type, false))) { + SLONG org; + + if ((org = area_AllocAnyBank(pSection->nByteSize, pSection->nAlign, type)) != -1) { + pSection->nOrg = org & 0xFFFF; + pSection->nBank = org >> 16; + pSection->oAssigned = 1; + DOMAXBANK(pSection->Type, pSection->nBank); + } else { + errx(1, "Unable to place %s section anywhere", + SECT_ATTRIBUTES[type].name); + } + } +} + void AssignSections(void) { @@ -353,35 +386,11 @@ AssignSections(void) } /* - * Next, let's assign all the bankfixed ONLY ROMX sections... + * Next, let's assign all the bankfixed ONLY sections... * */ - - pSection = pSections; - while (pSection) { - if (pSection->oAssigned == 0 - && pSection->nOrg == -1 && pSection->nBank != -1) { - switch (pSection->Type) { - case SECT_ROMX: - case SECT_SRAM: - case SECT_VRAM: - case SECT_WRAMX: - if (VerifyAndSetBank(pSection) && - (pSection->nOrg = area_Alloc(&BankFree[pSection->nBank], pSection->nByteSize)) != -1) { - pSection->oAssigned = 1; - DOMAXBANK(pSection->Type, pSection->nBank); - } else { - errx(1, "Unable to load fixed %s section into bank $%02lX", - SECT_ATTRIBUTES[pSection->Type].name, pSection->nBank); - } - break; - - default: // Handle other sections later - break; - } - } - - pSection = pSection->pNext; + for (enum eSectionType i = SECT_MIN; i <= SECT_MAX; i++) { + AssignFixedBankSections(i); } /* @@ -421,41 +430,9 @@ AssignSections(void) * sections * */ - - pSection = pSections; - while (pSection) { - if (pSection->oAssigned == 0) { - switch (pSection->Type) { - case SECT_WRAM0: - case SECT_HRAM: - case SECT_ROM0: - pSection->nBank = SECT_ATTRIBUTES[pSection->Type].bank; - if ((pSection->nOrg = - area_Alloc(&BankFree[pSection->nBank], - pSection->nByteSize)) == -1) { - errx(1, "%s section too large", SECT_ATTRIBUTES[pSection->Type].name); - } - pSection->oAssigned = 1; - break; - - case SECT_SRAM: - case SECT_VRAM: - case SECT_WRAMX: - case SECT_ROMX: - break; - - default: - errx(1, "(INTERNAL) Unknown section type!"); - break; - } - } - pSection = pSection->pNext; + for (enum eSectionType i = SECT_MIN; i <= SECT_MAX; i++) { + AssignFloatingBankSections(i); } - - AssignBankedSections(SECT_ROMX); - AssignBankedSections(SECT_VRAM); - AssignBankedSections(SECT_WRAMX); - AssignBankedSections(SECT_SRAM); } void diff --git a/src/link/object.c b/src/link/object.c index d216425d..5d0e7195 100644 --- a/src/link/object.c +++ b/src/link/object.c @@ -18,6 +18,11 @@ struct sSection *pLibSections = NULL; UBYTE dummymem; BBOOL oReadLib = 0; +enum ObjectFileContents { + CONTAINS_SECTION_NAME = 1 << 0, + CONTAINS_SECTION_ALIGNMENT = 1 << 1 +}; + /* * The usual byte order stuff * @@ -46,21 +51,41 @@ readword(FILE * f) return (r); } + /* * Read a NULL terminated string from a file * */ - -SLONG -readasciiz(char *s, FILE * f) +SLONG +readasciiz(char **dest, FILE *f) { SLONG r = 0; - - while (((*s++) = fgetc(f)) != 0) + + size_t bufferLength = 16; + char *start = malloc(bufferLength); + char *s = start; + + if (!s) { + err(1, NULL); + } + + while (((*s++) = fgetc(f)) != 0) { r += 1; - + + if (r >= bufferLength) { + bufferLength *= 2; + start = realloc(start, bufferLength); + if (!start) { + err(1, NULL); + } + s = start + r; + } + } + + *dest = start; return (r + 1); } + /* * Allocate a new section and link it into the list * @@ -97,7 +122,6 @@ AllocSection(void) struct sSymbol * obj_ReadSymbol(FILE * f) { - char s[256]; struct sSymbol *pSym; pSym = malloc(sizeof *pSym); @@ -105,13 +129,7 @@ obj_ReadSymbol(FILE * f) err(1, NULL); } - readasciiz(s, f); - pSym->pzName = malloc(strlen(s) + 1); - if (!pSym->pzName) { - err(1, NULL); - } - - strcpy(pSym->pzName, s); + readasciiz(&pSym->pzName, f); if ((pSym->Type = (enum eSymbolType) fgetc(f)) != SYM_IMPORT) { pSym->nSectionID = readlong(f); pSym->nOffset = readlong(f); @@ -130,10 +148,12 @@ obj_ReadRGB0Section(FILE * f) pSection = AllocSection(); + pSection->pzName = ""; pSection->nByteSize = readlong(f); pSection->Type = (enum eSectionType) fgetc(f); pSection->nOrg = -1; pSection->nBank = -1; + pSection->nAlign = 1; /* does the user want the -s mode? */ @@ -153,7 +173,6 @@ obj_ReadRGB0Section(FILE * f) SLONG nNumberOfPatches; struct sPatch **ppPatch, *pPatch; - char s[256]; fread(pSection->pData, sizeof(UBYTE), pSection->nByteSize, f); @@ -171,14 +190,7 @@ obj_ReadRGB0Section(FILE * f) } *ppPatch = pPatch; - readasciiz(s, f); - - pPatch->pzFilename = malloc(strlen(s) + 1); - if (!pPatch->pzFilename) { - err(1, NULL); - } - - strcpy(pPatch->pzFilename, s); + readasciiz(&pPatch->pzFilename, f); pPatch->nLineNo = readlong(f); @@ -272,21 +284,28 @@ obj_ReadRGB0(FILE * pObjfile) */ struct sSection * -obj_ReadRGB1Section(FILE * f) +obj_ReadRGBSection(FILE * f, enum ObjectFileContents contents) { struct sSection *pSection; pSection = AllocSection(); + if (contents & CONTAINS_SECTION_NAME) { + readasciiz(&pSection->pzName, f); + } else { + pSection->pzName = ""; + } + pSection->nByteSize = readlong(f); pSection->Type = (enum eSectionType) fgetc(f); - /* - * And because of THIS new feature I'll have to rewrite loads and - * loads of stuff... oh well it needed to be done anyway - * - */ pSection->nOrg = readlong(f); pSection->nBank = readlong(f); + + if (contents & CONTAINS_SECTION_ALIGNMENT) { + pSection->nAlign = readlong(f); + } else { + pSection->nAlign = 1; + } /* does the user want the -s mode? */ @@ -306,7 +325,6 @@ obj_ReadRGB1Section(FILE * f) SLONG nNumberOfPatches; struct sPatch **ppPatch, *pPatch; - char s[256]; fread(pSection->pData, sizeof(UBYTE), pSection->nByteSize, f); @@ -324,13 +342,7 @@ obj_ReadRGB1Section(FILE * f) } *ppPatch = pPatch; - readasciiz(s, f); - pPatch->pzFilename = malloc(strlen(s) + 1); - if (!pPatch->pzFilename) { - err(1, NULL); - } - - strcpy(pPatch->pzFilename, s); + readasciiz(&pPatch->pzFilename, f); pPatch->nLineNo = readlong(f); pPatch->nOffset = readlong(f); pPatch->Type = (enum ePatchType) fgetc(f); @@ -358,7 +370,7 @@ obj_ReadRGB1Section(FILE * f) } void -obj_ReadRGB1(FILE * pObjfile) +obj_ReadRGB(FILE * pObjfile, enum ObjectFileContents contents) { struct sSection *pFirstSection; SLONG nNumberOfSymbols, nNumberOfSections, i; @@ -385,7 +397,7 @@ obj_ReadRGB1(FILE * pObjfile) while (nNumberOfSections--) { struct sSection *pNewSection; - pNewSection = obj_ReadRGB1Section(pObjfile); + pNewSection = obj_ReadRGBSection(pObjfile, contents); pNewSection->nNumberOfSymbols = nNumberOfSymbols; if (pFirstSection == NULL) pFirstSection = pNewSection; @@ -432,7 +444,11 @@ obj_ReadOpenFile(FILE * pObjfile, char *tzObjectfile) case '1': case '2': //V2 is really the same but the are new patch types - obj_ReadRGB1(pObjfile); + obj_ReadRGB(pObjfile, 0); + break; + case '3': + // V3 is very similiar, but contains section names and byte alignment + obj_ReadRGB(pObjfile, CONTAINS_SECTION_NAME | CONTAINS_SECTION_ALIGNMENT); break; default: errx(1, "'%s' is an unsupported version", tzObjectfile); @@ -482,9 +498,9 @@ lib_ReadXLB0(FILE * f) size = file_Length(f) - 4; while (size) { - char name[256]; + char *name; - size -= readasciiz(name, f); + size -= readasciiz(&name, f); readword(f); size -= 2; readword(f); @@ -492,5 +508,6 @@ lib_ReadXLB0(FILE * f) size -= readlong(f); size -= 4; obj_ReadOpenFile(f, name); + free(name); } }