Implement VRAM banks.

This commit is contained in:
Anthony J. Bentley
2013-05-20 00:59:15 -06:00
parent 6ccd386587
commit 35448887af
3 changed files with 182 additions and 25 deletions

View File

@@ -7,9 +7,9 @@ enum eBankDefine {
BANK_HOME = 0, BANK_HOME = 0,
BANK_BSS = 512, BANK_BSS = 512,
BANK_VRAM, BANK_VRAM,
BANK_HRAM BANK_HRAM = 515
}; };
#define MAXBANKS 515 #define MAXBANKS 516
extern SLONG area_Avail(SLONG bank); extern SLONG area_Avail(SLONG bank);
extern void AssignSections(void); extern void AssignSections(void);

View File

@@ -17,8 +17,15 @@ section:
out_NewAbsSection($2,$4,-1,$8); out_NewAbsSection($2,$4,-1,$8);
else else
yyerror("ROM bank value $%x out of range (1 to $1ff)", $8); yyerror("ROM bank value $%x out of range (1 to $1ff)", $8);
} else } else if ($4 == SECT_VRAM) {
yyerror("BANK only allowed for CODE/DATA"); 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");
}
} }
| T_POP_SECTION string ',' sectiontype '[' const ']' ',' T_OP_BANK '[' const ']' | T_POP_SECTION string ',' sectiontype '[' const ']' ',' T_OP_BANK '[' const ']'
{ {
@@ -27,11 +34,22 @@ section:
if( $11>=1 && $11<=0x1ff ) if( $11>=1 && $11<=0x1ff )
out_NewAbsSection($2,$4,$6,$11); out_NewAbsSection($2,$4,$6,$11);
else else
yyerror("ROM bank value $%x out of range (1 to $1ff)", 8); yyerror("ROM bank value $%x out of range (1 to $1ff)", $11);
} else } else
yyerror("Address $%x not 16-bit", $6); yyerror("Address $%x not 16-bit", $6);
} else } else if ($4 == SECT_VRAM) {
yyerror("BANK only allowed for CODE/DATA"); if ($6 >= 0 && $6 < 0x10000) {
if ($11 >= 0 && $11 <= 1) {
out_NewAbsSection($2,$4,$6,$11);
} else {
yyerror("VRAM bank value $%x out of range (0 to 1)", $11);
}
} else {
yyerror("Address $%x not 16-bit", $6);
}
} else {
yyerror("BANK only allowed for CODE/DATA or VRAM sections");
}
} }
; ;

View File

@@ -15,8 +15,10 @@ struct sFreeArea {
struct sFreeArea *BankFree[MAXBANKS]; struct sFreeArea *BankFree[MAXBANKS];
SLONG MaxAvail[MAXBANKS]; SLONG MaxAvail[MAXBANKS];
SLONG MaxBankUsed; SLONG MaxBankUsed;
SLONG MaxVBankUsed;
#define DOMAXBANK(x) {if( (x)>MaxBankUsed ) MaxBankUsed=(x);} #define DOMAXBANK(x) {if( (x)>MaxBankUsed ) MaxBankUsed=(x);}
#define DOMAXVBANK(x) {if( (x)>MaxVBankUsed ) MaxVBankUsed=(x);}
SLONG SLONG
area_Avail(SLONG bank) area_Avail(SLONG bank)
@@ -85,6 +87,19 @@ area_AllocAbs(struct sFreeArea ** ppArea, SLONG org, SLONG size)
return (-1); return (-1);
} }
SLONG
area_AllocAbsVRAMAnyBank(SLONG org, SLONG size)
{
if (area_AllocAbs(&BankFree[BANK_VRAM], org, size) == org) {
return BANK_VRAM;
}
if (area_AllocAbs(&BankFree[BANK_VRAM + 1], org, size) == org) {
return BANK_VRAM + 1;
}
return -1;
}
SLONG SLONG
area_AllocAbsCODEAnyBank(SLONG org, SLONG size) area_AllocAbsCODEAnyBank(SLONG org, SLONG size)
{ {
@@ -121,6 +136,19 @@ area_Alloc(struct sFreeArea ** ppArea, SLONG size)
return (-1); return (-1);
} }
SLONG
area_AllocVRAMAnyBank(SLONG size)
{
SLONG i, org;
for (i = BANK_VRAM; i <= BANK_VRAM + 1; i += 1) {
if ((org = area_Alloc(&BankFree[i], size)) != -1)
return ((i << 16) | org);
}
return (-1);
}
SLONG SLONG
area_AllocCODEAnyBank(SLONG size) area_AllocCODEAnyBank(SLONG size)
{ {
@@ -134,6 +162,25 @@ area_AllocCODEAnyBank(SLONG size)
return (-1); return (-1);
} }
struct sSection *
FindLargestVRAM(void)
{
struct sSection *pSection, *r = NULL;
SLONG nLargest = 0;
pSection = pSections;
while (pSection) {
if (pSection->oAssigned == 0 && pSection->Type == SECT_VRAM) {
if (pSection->nByteSize > nLargest) {
nLargest = pSection->nByteSize;
r = pSection;
}
}
pSection = pSection->pNext;
}
return (r);
}
struct sSection * struct sSection *
FindLargestCode(void) FindLargestCode(void)
{ {
@@ -153,6 +200,27 @@ FindLargestCode(void)
return (r); return (r);
} }
void
AssignVRAMSections(void)
{
struct sSection *pSection;
while ((pSection = FindLargestVRAM())) {
SLONG org;
if ((org = area_AllocVRAMAnyBank(pSection->nByteSize)) != -1) {
pSection->nOrg = org & 0xFFFF;
pSection->nBank = org >> 16;
pSection->oAssigned = 1;
DOMAXVBANK(pSection->nBank);
} else {
fprintf(stderr,
"Unable to place VRAM section anywhere\n");
exit(1);
}
}
}
void void
AssignCodeSections(void) AssignCodeSections(void)
{ {
@@ -196,6 +264,7 @@ AssignSections(void)
} }
if (i == 0) { if (i == 0) {
/* ROM0 bank */
BankFree[i]->nOrg = 0x0000; BankFree[i]->nOrg = 0x0000;
if (options & OPT_SMALL) { if (options & OPT_SMALL) {
BankFree[i]->nSize = 0x8000; BankFree[i]->nSize = 0x8000;
@@ -205,6 +274,7 @@ AssignSections(void)
MaxAvail[i] = 0x4000; MaxAvail[i] = 0x4000;
} }
} else if (i >= 1 && i <= 511) { } else if (i >= 1 && i <= 511) {
/* Swappable ROM bank */
BankFree[i]->nOrg = 0x4000; BankFree[i]->nOrg = 0x4000;
/* /*
* Now, this shouldn't really be necessary... but for * Now, this shouldn't really be necessary... but for
@@ -218,14 +288,17 @@ AssignSections(void)
MaxAvail[i] = 0x4000; MaxAvail[i] = 0x4000;
} }
} else if (i == BANK_BSS) { } else if (i == BANK_BSS) {
/* WRAM */
BankFree[i]->nOrg = 0xC000; BankFree[i]->nOrg = 0xC000;
BankFree[i]->nSize = 0x2000; BankFree[i]->nSize = 0x2000;
MaxAvail[i] = 0x2000; MaxAvail[i] = 0x2000;
} else if (i == BANK_VRAM) { } else if (i == BANK_VRAM || i == BANK_VRAM + 1) {
/* Swappable VRAM bank */
BankFree[i]->nOrg = 0x8000; BankFree[i]->nOrg = 0x8000;
BankFree[i]->nSize = 0x2000; BankFree[i]->nSize = 0x2000;
MaxAvail[i] = 0x2000; MaxAvail[i] = 0x2000;
} else if (i == BANK_HRAM) { } else if (i == BANK_HRAM) {
/* HRAM */
BankFree[i]->nOrg = 0xFF80; BankFree[i]->nOrg = 0xFF80;
BankFree[i]->nSize = 0x007F; BankFree[i]->nSize = 0x007F;
MaxAvail[i] = 0x007F; MaxAvail[i] = 0x007F;
@@ -272,16 +345,57 @@ AssignSections(void)
pSection->nBank = BANK_HRAM; pSection->nBank = BANK_HRAM;
break; break;
case SECT_VRAM: case SECT_VRAM:
if (area_AllocAbs if (pSection->nBank == -1) {
(&BankFree[BANK_VRAM], pSection->nOrg, /*
pSection->nByteSize) != pSection->nOrg) { * User doesn't care which bank.
fprintf(stderr, "Unable to load fixed " * Therefore he must here be specifying
"VRAM section at $%lX\n", * position within the bank.
pSection->nOrg); * Defer until later.
exit(1); */
;
} 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 >= 0
&& pSection->nBank <= 1) {
pSection->nBank +=
BANK_VRAM;
if (area_AllocAbs
(&BankFree
[pSection->nBank],
pSection->nOrg,
pSection->nByteSize)
!= pSection->nOrg) {
fprintf(stderr,
"Unable to load fixed VRAM section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank - BANK_VRAM);
exit(1);
}
DOMAXVBANK(pSection->
nBank);
pSection->oAssigned = 1;
} else {
fprintf(stderr,
"Unable to load fixed VRAM section at $%lX in bank $%02lX\n", pSection->nOrg, pSection->nBank - BANK_VRAM);
exit(1);
}
}
} }
pSection->oAssigned = 1;
pSection->nBank = BANK_VRAM;
break; break;
case SECT_HOME: case SECT_HOME:
if (area_AllocAbs if (area_AllocAbs
@@ -378,6 +492,24 @@ AssignSections(void)
fprintf(stderr, "Unable to load fixed CODE/DATA section into bank $%02lX\n", pSection->nBank); fprintf(stderr, "Unable to load fixed CODE/DATA section into bank $%02lX\n", pSection->nBank);
exit(1); exit(1);
} }
} else if (pSection->oAssigned == 0
&& pSection->Type == SECT_VRAM
&& pSection->nOrg == -1 && pSection->nBank != -1) {
pSection->nBank += BANK_VRAM;
/* User wants to have a say... and he's pissed */
if (pSection->nBank >= BANK_VRAM && pSection->nBank <= BANK_VRAM + 1) {
if ((pSection->nOrg =
area_Alloc(&BankFree[pSection->nBank],
pSection->nByteSize)) == -1) {
fprintf(stderr, "Unable to load fixed VRAM section into bank $%02lX\n", pSection->nBank - BANK_VRAM);
exit(1);
}
pSection->oAssigned = 1;
DOMAXBANK(pSection->nBank);
} else {
fprintf(stderr, "Unable to load fixed VRAM section into bank $%02lX\n", pSection->nBank - BANK_VRAM);
exit(1);
}
} }
pSection = pSection->pNext; pSection = pSection->pNext;
} }
@@ -403,6 +535,20 @@ AssignSections(void)
} }
pSection->oAssigned = 1; pSection->oAssigned = 1;
DOMAXBANK(pSection->nBank); DOMAXBANK(pSection->nBank);
} else if (pSection->oAssigned == 0
&& pSection->Type == SECT_VRAM
&& pSection->nOrg != -1 && pSection->nBank == -1) {
/* User wants to have a say... and he's back with a
* vengeance */
if ((pSection->nBank =
area_AllocAbsVRAMAnyBank(pSection->nOrg,
pSection->nByteSize)) ==
-1) {
fprintf(stderr, "Unable to load fixed VRAM section at $%lX into any bank\n", pSection->nOrg);
exit(1);
}
pSection->oAssigned = 1;
DOMAXVBANK(pSection->nBank);
} }
pSection = pSection->pNext; pSection = pSection->pNext;
} }
@@ -438,14 +584,6 @@ AssignSections(void)
pSection->oAssigned = 1; pSection->oAssigned = 1;
break; break;
case SECT_VRAM: case SECT_VRAM:
if ((pSection->nOrg =
area_Alloc(&BankFree[BANK_VRAM],
pSection->nByteSize)) == -1) {
fprintf(stderr, "VRAM section too large\n");
exit(1);
}
pSection->nBank = BANK_VRAM;
pSection->oAssigned = 1;
break; break;
case SECT_HOME: case SECT_HOME:
if ((pSection->nOrg = if ((pSection->nOrg =
@@ -469,6 +607,7 @@ AssignSections(void)
} }
AssignCodeSections(); AssignCodeSections();
AssignVRAMSections();
} }
void void