mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 10:12:06 +00:00
Implement ENDSECTION (#1211)
This commit is contained in:
@@ -74,6 +74,7 @@ void sect_PCRelByte(struct Expression *expr, uint32_t pcShift);
|
||||
void sect_BinaryFile(char const *s, int32_t startPos);
|
||||
void sect_BinaryFileSlice(char const *s, int32_t start_pos, int32_t length);
|
||||
|
||||
void sect_EndSection(void);
|
||||
void sect_PushSection(void);
|
||||
void sect_PopSection(void);
|
||||
|
||||
|
||||
@@ -714,6 +714,11 @@ SECTION "OAM Data",WRAM0,ALIGN[8] ;\ align to 256 bytes
|
||||
SECTION "VRAM Data",ROMX,BANK[2],ALIGN[4] ;\ align to 16 bytes
|
||||
.Ed
|
||||
.El
|
||||
.Pp
|
||||
The current section can be ended without starting a new section by using
|
||||
.Ic ENDSECTION .
|
||||
This directive will clear the section context, so you can no longer write code until you start another section.
|
||||
It can be useful to avoid accidentally defining code or data in the wrong section.
|
||||
.Ss Section stack
|
||||
.Ic POPS
|
||||
and
|
||||
@@ -785,7 +790,7 @@ The former is situated in ROM, where the code is stored, the latter in RAM, wher
|
||||
.Pp
|
||||
You cannot nest
|
||||
.Ic LOAD
|
||||
blocks, nor can you change the current section within them.
|
||||
blocks, nor can you change or stop the current section within them.
|
||||
.Pp
|
||||
.Ic LOAD
|
||||
blocks can use the
|
||||
|
||||
@@ -258,7 +258,7 @@ size_t charmap_ConvertNext(char const **input, uint8_t **output)
|
||||
*input);
|
||||
|
||||
if (codepointLen == 0)
|
||||
error("Input string is not valid UTF-8!\n");
|
||||
error("Input string is not valid UTF-8\n");
|
||||
|
||||
// OK because UTF-8 has no NUL in multi-byte chars
|
||||
*input += codepointLen;
|
||||
|
||||
@@ -569,7 +569,7 @@ void fstk_Init(char const *mainPath, size_t maxDepth)
|
||||
struct LexerState *state = lexer_OpenFile(mainPath);
|
||||
|
||||
if (!state)
|
||||
fatalerror("Failed to open main file!\n");
|
||||
fatalerror("Failed to open main file\n");
|
||||
lexer_SetState(state);
|
||||
char const *fileName = lexer_GetFileName();
|
||||
size_t len = strlen(fileName);
|
||||
|
||||
@@ -217,6 +217,7 @@ static struct KeywordMapping {
|
||||
{"DW", T_POP_DW},
|
||||
{"DL", T_POP_DL},
|
||||
{"SECTION", T_POP_SECTION},
|
||||
{"ENDSECTION", T_POP_ENDSECTION},
|
||||
{"PURGE", T_POP_PURGE},
|
||||
|
||||
{"RSRESET", T_POP_RSRESET},
|
||||
@@ -572,7 +573,7 @@ struct KeywordDictNode {
|
||||
uint16_t children[0x60 - ' '];
|
||||
struct KeywordMapping const *keyword;
|
||||
// Since the keyword structure is invariant, the min number of nodes is known at compile time
|
||||
} keywordDict[370] = {0}; // Make sure to keep this correct when adding keywords!
|
||||
} keywordDict[377] = {0}; // Make sure to keep this correct when adding keywords!
|
||||
|
||||
// Convert a char into its index into the dict
|
||||
static uint8_t dictIndex(char c)
|
||||
|
||||
@@ -632,6 +632,7 @@ enum {
|
||||
%token T_POP_EXPORT "EXPORT"
|
||||
%token T_POP_DB "DB" T_POP_DS "DS" T_POP_DW "DW" T_POP_DL "DL"
|
||||
%token T_POP_SECTION "SECTION" T_POP_FRAGMENT "FRAGMENT"
|
||||
%token T_POP_ENDSECTION "ENDSECTION"
|
||||
%token T_POP_RB "RB" T_POP_RW "RW" // There is no T_POP_RL, only T_Z80_RL
|
||||
%token T_POP_MACRO "MACRO"
|
||||
%token T_POP_ENDM "ENDM"
|
||||
@@ -936,6 +937,7 @@ directive : endc
|
||||
| purge
|
||||
| pops
|
||||
| pushs
|
||||
| endsection
|
||||
| popo
|
||||
| pusho
|
||||
| opt
|
||||
@@ -1056,6 +1058,9 @@ pops : T_POP_POPS { sect_PopSection(); }
|
||||
pushs : T_POP_PUSHS { sect_PushSection(); }
|
||||
;
|
||||
|
||||
endsection : T_POP_ENDSECTION { sect_EndSection(); }
|
||||
;
|
||||
|
||||
fail : T_POP_FAIL string { fatalerror("%s\n", $2); }
|
||||
;
|
||||
|
||||
|
||||
@@ -598,7 +598,7 @@ void sect_EndUnion(void)
|
||||
void sect_CheckUnionClosed(void)
|
||||
{
|
||||
if (unionStack)
|
||||
error("Unterminated UNION construct!\n");
|
||||
error("Unterminated UNION construct\n");
|
||||
}
|
||||
|
||||
// Output an absolute byte
|
||||
@@ -965,7 +965,7 @@ void sect_PopSection(void)
|
||||
fatalerror("No entries in the section stack\n");
|
||||
|
||||
if (currentLoadSection)
|
||||
fatalerror("Cannot change the section within a `LOAD` block!\n");
|
||||
fatalerror("Cannot change the section within a `LOAD` block\n");
|
||||
|
||||
struct SectionStackEntry *entry = sectionStack;
|
||||
|
||||
@@ -981,6 +981,22 @@ void sect_PopSection(void)
|
||||
free(entry);
|
||||
}
|
||||
|
||||
void sect_EndSection(void)
|
||||
{
|
||||
if (!currentSection)
|
||||
fatalerror("Cannot end the section outside of a SECTION\n");
|
||||
|
||||
if (currentLoadSection)
|
||||
fatalerror("Cannot end the section within a `LOAD` block\n");
|
||||
|
||||
if (unionStack)
|
||||
fatalerror("Cannot end the section within a UNION\n");
|
||||
|
||||
// Reset the section scope
|
||||
currentSection = NULL;
|
||||
sym_SetCurrentSymbolScope(NULL);
|
||||
}
|
||||
|
||||
bool sect_IsSizeKnown(struct Section const NONNULL(sect))
|
||||
{
|
||||
// SECTION UNION and SECTION FRAGMENT can still grow
|
||||
|
||||
@@ -242,7 +242,7 @@ static void registerInput(char const *arg) {
|
||||
printUsage();
|
||||
exit(1);
|
||||
} else if (arg[0] == '\0') { // Empty input path
|
||||
fprintf(stderr, "FATAL: input image path cannot be empty!\n");
|
||||
fprintf(stderr, "FATAL: input image path cannot be empty\n");
|
||||
printUsage();
|
||||
exit(1);
|
||||
} else {
|
||||
|
||||
@@ -109,8 +109,8 @@ void reverse() {
|
||||
auto const tiles = readInto(options.output);
|
||||
uint8_t tileSize = 8 * options.bitDepth;
|
||||
if (tiles.size() % tileSize != 0) {
|
||||
fatal("Tile data size must be a multiple of %" PRIu8 " bytes! (Read %zu)", tileSize,
|
||||
tiles.size());
|
||||
fatal("Tile data size (%zu bytes) is not a multiple of %" PRIu8 " bytes",
|
||||
tiles.size(), tileSize);
|
||||
}
|
||||
|
||||
// By default, assume tiles are not deduplicated, and add the (allegedly) trimmed tiles
|
||||
|
||||
4
test/asm/endsection.asm
Normal file
4
test/asm/endsection.asm
Normal file
@@ -0,0 +1,4 @@
|
||||
SECTION "test", ROM0
|
||||
db 1
|
||||
ENDSECTION
|
||||
db 2
|
||||
3
test/asm/endsection.err
Normal file
3
test/asm/endsection.err
Normal file
@@ -0,0 +1,3 @@
|
||||
error: endsection.asm(4):
|
||||
Cannot output data outside of a SECTION
|
||||
error: Assembly aborted (1 error)!
|
||||
0
test/asm/endsection.out
Normal file
0
test/asm/endsection.out
Normal file
Reference in New Issue
Block a user