diff --git a/include/asm/mylink.h b/include/asm/mylink.h index 0586b77b..1b6d93e0 100644 --- a/include/asm/mylink.h +++ b/include/asm/mylink.h @@ -99,7 +99,8 @@ enum { SECT_VRAM, SECT_CODE, SECT_HOME, - SECT_HRAM + SECT_HRAM, + SECT_WRAMX }; enum { diff --git a/include/link/assign.h b/include/link/assign.h index 9c522617..076801c7 100644 --- a/include/link/assign.h +++ b/include/link/assign.h @@ -6,10 +6,11 @@ enum eBankDefine { BANK_HOME = 0, BANK_BSS = 512, - BANK_VRAM, - BANK_HRAM = 515 + BANK_WRAMX, + BANK_VRAM = 520, + BANK_HRAM = 522 }; -#define MAXBANKS 516 +#define MAXBANKS 523 extern SLONG area_Avail(SLONG bank); extern void AssignSections(void); diff --git a/include/link/mylink.h b/include/link/mylink.h index 25b52c56..2999a1a4 100644 --- a/include/link/mylink.h +++ b/include/link/mylink.h @@ -53,7 +53,8 @@ enum eSectionType { SECT_VRAM, SECT_CODE, SECT_HOME, - SECT_HRAM + SECT_HRAM, + SECT_WRAMX }; struct sSection { diff --git a/src/asm/gameboy/yaccprt2.y b/src/asm/gameboy/yaccprt2.y index 2191e6ce..906b399d 100644 --- a/src/asm/gameboy/yaccprt2.y +++ b/src/asm/gameboy/yaccprt2.y @@ -1,4 +1,4 @@ -%token T_SECT_BSS T_SECT_VRAM T_SECT_CODE T_SECT_HOME T_SECT_HRAM +%token T_SECT_BSS T_SECT_VRAM T_SECT_CODE T_SECT_HOME T_SECT_HRAM T_SECT_WRAMX %token T_Z80_ADC T_Z80_ADD T_Z80_AND %token T_Z80_BIT diff --git a/src/asm/gameboy/yaccprt4.y b/src/asm/gameboy/yaccprt4.y index 061f3397..0e28d5cb 100644 --- a/src/asm/gameboy/yaccprt4.y +++ b/src/asm/gameboy/yaccprt4.y @@ -17,14 +17,20 @@ section: out_NewAbsSection($2,$4,-1,$8); else yyerror("ROM bank value $%x out of range (1 to $1ff)", $8); + } else if ($4 == SECT_WRAMX) { + if ($8 >= 1 && $8 <= 7) { + out_NewAbsSection($2, $4, -1, $8); + } else { + yyerror("WRAMX bank value $%x out of range (1 to 7)", $8); + } } else if ($4 == SECT_VRAM) { - if ($8 >= 0 && $8 <= 1) { + if ($8 >= 0 && $8 <= 1) { out_NewAbsSection($2, $4, -1, $8); } else { yyerror("VRAM bank value $%x out of range (0 to 1)", $8); } } else { - yyerror("BANK only allowed for CODE/DATA or VRAM sections"); + yyerror("BANK only allowed for CODE/DATA, WRAMX, or VRAM sections"); } } | T_POP_SECTION string ',' sectiontype '[' const ']' ',' T_OP_BANK '[' const ']' @@ -37,6 +43,16 @@ section: yyerror("ROM bank value $%x out of range (1 to $1ff)", $11); } else yyerror("Address $%x not 16-bit", $6); + } else if ($4 == SECT_WRAMX) { + if ($6 >= 0 && $6 < 0x10000) { + if ($11 >= 1 && $11 <= 7) { + out_NewAbsSection($2, $4, $6, $11); + } else { + yyerror("WRAMX bank value $%x out of range (1 to 7)", $11); + } + } else { + yyerror("Address $%x not 16-bit", $6); + } } else if ($4 == SECT_VRAM) { if ($6 >= 0 && $6 < 0x10000) { if ($11 >= 0 && $11 <= 1) { @@ -48,7 +64,7 @@ section: yyerror("Address $%x not 16-bit", $6); } } else { - yyerror("BANK only allowed for CODE/DATA or VRAM sections"); + yyerror("BANK only allowed for CODE/DATA, WRAMX, or VRAM sections"); } } ; @@ -59,6 +75,7 @@ sectiontype: | T_SECT_CODE { $$=SECT_CODE; } | T_SECT_HOME { $$=SECT_HOME; } | T_SECT_HRAM { $$=SECT_HRAM; } + | T_SECT_WRAMX { $$=SECT_WRAMX; } ; diff --git a/src/asm/globlex.c b/src/asm/globlex.c index 6309b4be..41332008 100644 --- a/src/asm/globlex.c +++ b/src/asm/globlex.c @@ -322,6 +322,7 @@ struct sLexInitString staticstrings[] = { {"data", T_SECT_CODE}, {"home", T_SECT_HOME}, {"hram", T_SECT_HRAM}, + {"wramx", T_SECT_WRAMX}, {NAME_RB, T_POP_RB}, {NAME_RW, T_POP_RW}, diff --git a/src/link/assign.c b/src/link/assign.c index f0b2e4fa..2ca05aea 100644 --- a/src/link/assign.c +++ b/src/link/assign.c @@ -15,9 +15,11 @@ struct sFreeArea { struct sFreeArea *BankFree[MAXBANKS]; SLONG MaxAvail[MAXBANKS]; SLONG MaxBankUsed; +SLONG MaxWBankUsed; SLONG MaxVBankUsed; #define DOMAXBANK(x) {if( (x)>MaxBankUsed ) MaxBankUsed=(x);} +#define DOMAXWBANK(x) {if( (x)>MaxWBankUsed ) MaxWBankUsed=(x);} #define DOMAXVBANK(x) {if( (x)>MaxVBankUsed ) MaxVBankUsed=(x);} SLONG @@ -87,6 +89,20 @@ area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size) return (-1); } +SLONG +area_AllocAbsWRAMAnyBank(SLONG org, SLONG size) +{ + SLONG i; + + for (i = 1; i <= 7; i += 1) { + if (area_AllocAbs(&BankFree[BANK_WRAMX + i - 1], org, size) == org) { + return BANK_WRAMX + i - 1; + } + } + + return -1; +} + SLONG area_AllocAbsVRAMAnyBank(SLONG org, SLONG size) { @@ -149,6 +165,20 @@ area_AllocVRAMAnyBank(SLONG size) return (-1); } +SLONG +area_AllocWRAMAnyBank(SLONG size) +{ + SLONG i, org; + + for (i = 1; i <= 7; i += 1) { + if ((org = area_Alloc(&BankFree[BANK_WRAMX + i - 1], size)) != -1) { + return (i << 16) | org; + } + } + + return -1; +} + SLONG area_AllocCODEAnyBank(SLONG size) { @@ -162,6 +192,25 @@ area_AllocCODEAnyBank(SLONG size) return (-1); } +struct sSection * +FindLargestWRAM(void) +{ + struct sSection *pSection, *r = NULL; + SLONG nLargest = 0; + + pSection = pSections; + while (pSection) { + if (pSection->oAssigned == 0 && pSection->Type == SECT_WRAMX) { + if (pSection->nByteSize > nLargest) { + nLargest = pSection->nByteSize; + r = pSection; + } + } + pSection = pSection->pNext; + } + return r; +} + struct sSection * FindLargestVRAM(void) { @@ -178,7 +227,7 @@ FindLargestVRAM(void) } pSection = pSection->pNext; } - return (r); + return r; } struct sSection * @@ -221,6 +270,27 @@ AssignVRAMSections(void) } } +void +AssignWRAMSections(void) +{ + struct sSection *pSection; + + while ((pSection = FindLargestWRAM())) { + SLONG org; + + if ((org = area_AllocWRAMAnyBank(pSection->nByteSize)) != -1) { + pSection->nOrg = org & 0xFFFF; + pSection->nBank = org >> 16; + pSection->oAssigned = 1; + DOMAXWBANK(pSection->nBank); + } else { + fprintf(stderr, + "Unable to place WRAMX section anywhere\n"); + exit(1); + } + } +} + void AssignCodeSections(void) { @@ -290,8 +360,13 @@ AssignSections(void) } else if (i == BANK_BSS) { /* WRAM */ BankFree[i]->nOrg = 0xC000; - BankFree[i]->nSize = 0x2000; - MaxAvail[i] = 0x2000; + BankFree[i]->nSize = 0x1000; + MaxAvail[i] = 0x1000; + } else if (i >= BANK_WRAMX && i <= BANK_WRAMX + 6) { + /* Swappable VRAM bank */ + BankFree[i]->nOrg = 0xD000; + BankFree[i]->nSize = 0x1000; + MaxAvail[i] = 0x1000; } else if (i == BANK_VRAM || i == BANK_VRAM + 1) { /* Swappable VRAM bank */ BankFree[i]->nOrg = 0x8000; @@ -344,6 +419,59 @@ AssignSections(void) pSection->oAssigned = 1; pSection->nBank = BANK_HRAM; break; + case SECT_WRAMX: + if (pSection->nBank == -1) { + /* + * User doesn't care which bank. + * Therefore he must here be specifying + * position within the bank. + * Defer until later. + */ + ; + } else { + /* + * User specified which bank to use. + * Does he also care about position + * within the bank? + */ + if (pSection->nOrg == -1) { + /* + * Nope, any position will do + * Again, we'll do that later + * + */ + ; + } else { + /* + * Bank and position within the + * bank are hardcoded. + */ + + if (pSection->nBank >= 1 + && pSection->nBank <= 7) { + pSection->nBank += + BANK_WRAMX; + if (area_AllocAbs + (&BankFree + [pSection->nBank], + pSection->nOrg, + pSection->nByteSize) + != pSection->nOrg) { + fprintf(stderr, +"Unable to load fixed WRAMX section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank); + exit(1); + } + DOMAXWBANK(pSection-> + nBank); + pSection->oAssigned = 1; + } else { + fprintf(stderr, +"Unable to load fixed WRAMX section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank); + exit(1); + } + } + } + break; case SECT_VRAM: if (pSection->nBank == -1) { /* @@ -383,7 +511,7 @@ AssignSections(void) pSection->nByteSize) != pSection->nOrg) { fprintf(stderr, -"Unable to load fixed VRAM section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank - BANK_VRAM); +"Unable to load fixed VRAM section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank); exit(1); } DOMAXVBANK(pSection-> @@ -391,7 +519,7 @@ AssignSections(void) pSection->oAssigned = 1; } else { fprintf(stderr, -"Unable to load fixed VRAM section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank - BANK_VRAM); +"Unable to load fixed VRAM section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank); exit(1); } } @@ -505,11 +633,29 @@ AssignSections(void) exit(1); } pSection->oAssigned = 1; - DOMAXBANK(pSection->nBank); + DOMAXVBANK(pSection->nBank); } else { fprintf(stderr, "Unable to load fixed VRAM section into bank $%02lX\n", pSection->nBank - BANK_VRAM); exit(1); } + } else if (pSection->oAssigned == 0 + && pSection->Type == SECT_WRAMX + && pSection->nOrg == -1 && pSection->nBank != -1) { + pSection->nBank += BANK_WRAMX; + /* User wants to have a say... and he's pissed */ + if (pSection->nBank >= BANK_WRAMX && pSection->nBank <= BANK_WRAMX + 6) { + if ((pSection->nOrg = + area_Alloc(&BankFree[pSection->nBank], + pSection->nByteSize)) == -1) { + fprintf(stderr, "Unable to load fixed WRAMX section into bank $%02lX\n", pSection->nBank - BANK_WRAMX); + exit(1); + } + pSection->oAssigned = 1; + DOMAXWBANK(pSection->nBank); + } else { + fprintf(stderr, "Unable to load fixed WRAMX section into bank $%02lX\n", pSection->nBank - BANK_WRAMX); + exit(1); + } } pSection = pSection->pNext; } @@ -549,6 +695,20 @@ AssignSections(void) } pSection->oAssigned = 1; DOMAXVBANK(pSection->nBank); + } else if (pSection->oAssigned == 0 + && pSection->Type == SECT_WRAMX + && pSection->nOrg != -1 && pSection->nBank == -1) { + /* User wants to have a say... and he's back with a + * vengeance */ + if ((pSection->nBank = + area_AllocAbsWRAMAnyBank(pSection->nOrg, + pSection->nByteSize)) == + -1) { + fprintf(stderr, "Unable to load fixed WRAMX section at $%lX into any bank\n", pSection->nOrg); + exit(1); + } + pSection->oAssigned = 1; + DOMAXWBANK(pSection->nBank); } pSection = pSection->pNext; } @@ -585,6 +745,8 @@ AssignSections(void) break; case SECT_VRAM: break; + case SECT_WRAMX: + break; case SECT_HOME: if ((pSection->nOrg = area_Alloc(&BankFree[BANK_HOME], @@ -608,6 +770,7 @@ AssignSections(void) AssignCodeSections(); AssignVRAMSections(); + AssignWRAMSections(); } void diff --git a/src/link/mapfile.c b/src/link/mapfile.c index cb7e3f3a..f5a7f67c 100644 --- a/src/link/mapfile.c +++ b/src/link/mapfile.c @@ -65,8 +65,8 @@ MapfileInitBank(SLONG bank) fprintf(mf, "BSS:\n"); else if (bank == BANK_HRAM) fprintf(mf, "HRAM:\n"); - else if (bank == BANK_VRAM) - fprintf(mf, "VRAM:\n"); + else if (bank == BANK_VRAM || bank == BANK_VRAM + 1) + fprintf(mf, "VRAM Bank #%ld:\n", bank - BANK_VRAM); } if (sf) { sfbank = (bank >= 1 && bank <= 511) ? bank : 0;