mirror of
https://github.com/gbdev/rgbds.git
synced 2025-11-20 18:22:07 +00:00
Clean up some #define callables
These are used where anonymous functions would not be sufficient
This commit is contained in:
@@ -180,21 +180,21 @@ int main(int argc, char *argv[]) {
|
||||
options.fixSpec = 0;
|
||||
while (*musl_optarg) {
|
||||
switch (*musl_optarg) {
|
||||
#define OVERRIDE_SPEC(cur, bad, curFlag, badFlag) \
|
||||
case STR(cur)[0]: \
|
||||
#define overrideSpec(cur, bad, curFlag, badFlag) \
|
||||
case cur: \
|
||||
if (options.fixSpec & badFlag) { \
|
||||
warnx("'" STR(cur) "' overriding '" STR(bad) "' in fix spec"); \
|
||||
warnx("'%c' overriding '%c' in fix spec", cur, bad); \
|
||||
} \
|
||||
options.fixSpec = (options.fixSpec & ~badFlag) | curFlag; \
|
||||
break
|
||||
#define overrideSpecs(fix, fixFlag, trash, trashFlag) \
|
||||
OVERRIDE_SPEC(fix, trash, fixFlag, trashFlag); \
|
||||
OVERRIDE_SPEC(trash, fix, trashFlag, fixFlag)
|
||||
overrideSpecs(l, FIX_LOGO, L, TRASH_LOGO);
|
||||
overrideSpecs(h, FIX_HEADER_SUM, H, TRASH_HEADER_SUM);
|
||||
overrideSpecs(g, FIX_GLOBAL_SUM, G, TRASH_GLOBAL_SUM);
|
||||
#undef OVERRIDE_SPEC
|
||||
#undef overrideSpecs
|
||||
#define overrideSpecPair(fix, fixFlag, trash, trashFlag) \
|
||||
overrideSpec(fix, trash, fixFlag, trashFlag); \
|
||||
overrideSpec(trash, fix, trashFlag, fixFlag)
|
||||
overrideSpecPair('l', FIX_LOGO, 'L', TRASH_LOGO);
|
||||
overrideSpecPair('h', FIX_HEADER_SUM, 'H', TRASH_HEADER_SUM);
|
||||
overrideSpecPair('g', FIX_GLOBAL_SUM, 'G', TRASH_GLOBAL_SUM);
|
||||
#undef overrideSpec
|
||||
#undef overrideSpecPair
|
||||
|
||||
default:
|
||||
fatal("Invalid character '%c' in fix spec", *musl_optarg);
|
||||
|
||||
@@ -188,14 +188,6 @@ static bool readLine(std::filebuf &file, std::string &buffer) {
|
||||
}
|
||||
}
|
||||
|
||||
#define requireLine(kind, filename, file, buffer) \
|
||||
do { \
|
||||
if (!readLine(file, buffer)) { \
|
||||
error(kind " palette file \"%s\" is shorter than expected", filename); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
static void warnExtraColors(
|
||||
char const *kind, char const *filename, uint16_t nbColors, uint16_t maxNbColors
|
||||
) {
|
||||
@@ -254,21 +246,28 @@ static std::optional<Rgba> parseColor(std::string const &str, size_t &n, uint16_
|
||||
static void parsePSPFile(char const *filename, std::filebuf &file) {
|
||||
// https://www.selapa.net/swatches/colors/fileformats.php#psp_pal
|
||||
|
||||
#define requireLine() \
|
||||
do { \
|
||||
line.clear(); \
|
||||
if (!readLine(file, line)) { \
|
||||
error("PSP palette file \"%s\" is shorter than expected", filename); \
|
||||
return; \
|
||||
} \
|
||||
} while (0)
|
||||
|
||||
std::string line;
|
||||
if (!readLine(file, line) || line != "JASC-PAL") {
|
||||
error("File \"%s\" is not a valid PSP palette file", filename);
|
||||
return;
|
||||
}
|
||||
|
||||
line.clear();
|
||||
requireLine("PSP", filename, file, line);
|
||||
requireLine();
|
||||
if (line != "0100") {
|
||||
error("Unsupported PSP palette file version \"%s\"", line.c_str());
|
||||
return;
|
||||
}
|
||||
|
||||
line.clear();
|
||||
requireLine("PSP", filename, file, line);
|
||||
requireLine();
|
||||
size_t n = 0;
|
||||
std::optional<uint16_t> nbColors = parseDec<uint16_t>(line, n);
|
||||
if (!nbColors || n != line.length()) {
|
||||
@@ -284,8 +283,7 @@ static void parsePSPFile(char const *filename, std::filebuf &file) {
|
||||
options.palSpec.clear();
|
||||
|
||||
for (uint16_t i = 0; i < *nbColors; ++i) {
|
||||
line.clear();
|
||||
requireLine("PSP", filename, file, line);
|
||||
requireLine();
|
||||
|
||||
n = 0;
|
||||
std::optional<Rgba> color = parseColor(line, n, i + 1);
|
||||
@@ -306,6 +304,8 @@ static void parsePSPFile(char const *filename, std::filebuf &file) {
|
||||
}
|
||||
options.palSpec.back()[i % options.nbColorsPerPal] = *color;
|
||||
}
|
||||
|
||||
#undef requireLine
|
||||
}
|
||||
|
||||
static void parseGPLFile(char const *filename, std::filebuf &file) {
|
||||
|
||||
@@ -138,23 +138,30 @@ void sdobj_ReadFile(FileStackNode const &src, FILE *file, std::vector<Symbol> &f
|
||||
line.reserve(256);
|
||||
char const *token;
|
||||
|
||||
#define getToken(ptr, ...) \
|
||||
do { \
|
||||
token = strtok((ptr), delim); \
|
||||
if (!token) { \
|
||||
fatalAt(where, __VA_ARGS__); \
|
||||
} \
|
||||
} while (0)
|
||||
#define expectEol(...) \
|
||||
#define expectEol(lineType) \
|
||||
do { \
|
||||
token = strtok(nullptr, delim); \
|
||||
if (token) { \
|
||||
fatalAt(where, __VA_ARGS__); \
|
||||
fatalAt(where, "'%c' line is too long", (lineType)); \
|
||||
} \
|
||||
} while (0)
|
||||
#define expectNext(ptr, lineType) \
|
||||
do { \
|
||||
token = strtok((ptr), delim); \
|
||||
if (!token) { \
|
||||
fatalAt(where, "'%c' line is too short", (lineType)); \
|
||||
} \
|
||||
} while (0)
|
||||
#define expectRelocation() \
|
||||
do { \
|
||||
token = strtok(nullptr, delim); \
|
||||
if (!token) { \
|
||||
fatalAt(where, "Incomplete relocation"); \
|
||||
} \
|
||||
} while (0)
|
||||
#define expectToken(expected, lineType) \
|
||||
do { \
|
||||
getToken(nullptr, "'%c' line is too short", (lineType)); \
|
||||
expectNext(nullptr, lineType); \
|
||||
if (strcasecmp(token, (expected)) != 0) { \
|
||||
fatalAt( \
|
||||
where, \
|
||||
@@ -223,12 +230,15 @@ void sdobj_ReadFile(FileStackNode const &src, FILE *file, std::vector<Symbol> &f
|
||||
}
|
||||
// Expected format: "A areas S global symbols"
|
||||
|
||||
getToken(line.data(), "Empty 'H' line");
|
||||
token = strtok(line.data(), delim);
|
||||
if (!token) {
|
||||
fatalAt(where, "Empty 'H' line");
|
||||
}
|
||||
uint32_t expectedNbAreas = readInt(where, token, numberBase);
|
||||
|
||||
expectToken("areas", 'H');
|
||||
|
||||
getToken(nullptr, "'H' line is too short");
|
||||
expectNext(nullptr, 'H');
|
||||
uint32_t expectedNbSymbols = readInt(where, token, numberBase);
|
||||
fileSymbols.reserve(expectedNbSymbols);
|
||||
|
||||
@@ -236,7 +246,7 @@ void sdobj_ReadFile(FileStackNode const &src, FILE *file, std::vector<Symbol> &f
|
||||
|
||||
expectToken("symbols", 'H');
|
||||
|
||||
expectEol("'H' line is too long");
|
||||
expectEol('H');
|
||||
|
||||
// Now, let's parse the rest of the lines as they come!
|
||||
|
||||
@@ -267,7 +277,7 @@ void sdobj_ReadFile(FileStackNode const &src, FILE *file, std::vector<Symbol> &f
|
||||
curSection->src = where.src;
|
||||
curSection->lineNo = where.lineNo;
|
||||
|
||||
getToken(line.data(), "'A' line is too short");
|
||||
expectNext(line.data(), 'A');
|
||||
assume(strlen(token) != 0); // This should be impossible, tokens are non-empty
|
||||
// The following is required for fragment offsets to be reliably predicted
|
||||
for (FileSection &entry : fileSections) {
|
||||
@@ -279,7 +289,7 @@ void sdobj_ReadFile(FileStackNode const &src, FILE *file, std::vector<Symbol> &f
|
||||
|
||||
expectToken("size", 'A');
|
||||
|
||||
getToken(nullptr, "'A' line is too short");
|
||||
expectNext(nullptr, 'A');
|
||||
|
||||
uint32_t tmp = readInt(where, token, numberBase);
|
||||
|
||||
@@ -294,7 +304,7 @@ void sdobj_ReadFile(FileStackNode const &src, FILE *file, std::vector<Symbol> &f
|
||||
|
||||
expectToken("flags", 'A');
|
||||
|
||||
getToken(nullptr, "'A' line is too short");
|
||||
expectNext(nullptr, 'A');
|
||||
tmp = readInt(where, token, numberBase);
|
||||
if (tmp & (1 << AREA_PAGING)) {
|
||||
fatalAt(where, "Paging is not supported");
|
||||
@@ -313,12 +323,12 @@ void sdobj_ReadFile(FileStackNode const &src, FILE *file, std::vector<Symbol> &f
|
||||
|
||||
expectToken("addr", 'A');
|
||||
|
||||
getToken(nullptr, "'A' line is too short");
|
||||
expectNext(nullptr, 'A');
|
||||
tmp = readInt(where, token, numberBase);
|
||||
curSection->org = tmp; // Truncation keeps the address portion only
|
||||
curSection->bank = tmp >> 16;
|
||||
|
||||
expectEol("'A' line is too long");
|
||||
expectEol('A');
|
||||
|
||||
// Init the rest of the members
|
||||
curSection->offset = 0;
|
||||
@@ -366,10 +376,10 @@ void sdobj_ReadFile(FileStackNode const &src, FILE *file, std::vector<Symbol> &f
|
||||
symbol.src = where.src;
|
||||
symbol.lineNo = where.lineNo;
|
||||
|
||||
getToken(line.data(), "'S' line is too short");
|
||||
expectNext(line.data(), 'S');
|
||||
symbol.name = token;
|
||||
|
||||
getToken(nullptr, "'S' line is too short");
|
||||
expectNext(nullptr, 'S');
|
||||
|
||||
if (int32_t value = readInt(where, &token[3], numberBase); !fileSections.empty()) {
|
||||
// Symbols in sections are labels; their value is an offset
|
||||
@@ -438,7 +448,7 @@ void sdobj_ReadFile(FileStackNode const &src, FILE *file, std::vector<Symbol> &f
|
||||
fileSections.back().section->symbols.push_back(&symbol);
|
||||
}
|
||||
|
||||
expectEol("'S' line is too long");
|
||||
expectEol('S');
|
||||
break;
|
||||
}
|
||||
|
||||
@@ -467,13 +477,13 @@ void sdobj_ReadFile(FileStackNode const &src, FILE *file, std::vector<Symbol> &f
|
||||
}
|
||||
|
||||
// First two bytes are ignored
|
||||
getToken(line.data(), "'R' line is too short");
|
||||
getToken(nullptr, "'R' line is too short");
|
||||
expectNext(line.data(), 'R');
|
||||
expectNext(nullptr, 'R');
|
||||
uint16_t areaIdx;
|
||||
|
||||
getToken(nullptr, "'R' line is too short");
|
||||
expectNext(nullptr, 'R');
|
||||
areaIdx = readByte(where, token, numberBase);
|
||||
getToken(nullptr, "'R' line is too short");
|
||||
expectNext(nullptr, 'R');
|
||||
areaIdx |= static_cast<uint16_t>(readByte(where, token, numberBase)) << 8;
|
||||
if (areaIdx >= fileSections.size()) {
|
||||
fatalAt(
|
||||
@@ -537,12 +547,12 @@ void sdobj_ReadFile(FileStackNode const &src, FILE *file, std::vector<Symbol> &f
|
||||
uint16_t flags = readByte(where, token, numberBase);
|
||||
|
||||
if ((flags & 0xF0) == 0xF0) {
|
||||
getToken(nullptr, "Incomplete relocation");
|
||||
expectRelocation();
|
||||
flags = (flags & 0x0F)
|
||||
| static_cast<uint16_t>(readByte(where, token, numberBase)) << 4;
|
||||
}
|
||||
|
||||
getToken(nullptr, "Incomplete relocation");
|
||||
expectRelocation();
|
||||
uint8_t offset = readByte(where, token, numberBase);
|
||||
|
||||
if (offset < addrSize) {
|
||||
@@ -562,10 +572,10 @@ void sdobj_ReadFile(FileStackNode const &src, FILE *file, std::vector<Symbol> &f
|
||||
);
|
||||
}
|
||||
|
||||
getToken(nullptr, "Incomplete relocation");
|
||||
expectRelocation();
|
||||
uint16_t idx = readByte(where, token, numberBase);
|
||||
|
||||
getToken(nullptr, "Incomplete relocation");
|
||||
expectRelocation();
|
||||
idx |= static_cast<uint16_t>(readByte(where, token, numberBase));
|
||||
|
||||
// Loudly fail on unknown flags
|
||||
@@ -819,8 +829,9 @@ void sdobj_ReadFile(FileStackNode const &src, FILE *file, std::vector<Symbol> &f
|
||||
}
|
||||
|
||||
#undef expectEol
|
||||
#undef expectNext
|
||||
#undef expectRelocation
|
||||
#undef expectToken
|
||||
#undef getToken
|
||||
|
||||
if (!data.empty()) {
|
||||
warningAt(where, "Last 'T' line had no 'R' line (ignored)");
|
||||
|
||||
Reference in New Issue
Block a user