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