Add more tests for RGBFIX

This commit is contained in:
Rangi
2025-09-28 16:58:46 -04:00
parent 538395b92c
commit eea277ae9c
34 changed files with 275 additions and 88 deletions

View File

@@ -240,16 +240,17 @@ static void
std::vector<uint8_t> romx; // Buffer of ROMX bank data std::vector<uint8_t> romx; // Buffer of ROMX bank data
uint32_t nbBanks = 1; // Number of banks *targeted*, including ROM0 uint32_t nbBanks = 1; // Number of banks *targeted*, including ROM0
size_t totalRomxLen = 0; // *Actual* size of ROMX data size_t totalRomxLen = 0; // *Actual* size of ROMX data
uint8_t bank[BANK_SIZE]; // Temp buffer used to store a whole bank's worth of data
// Handle ROMX // Handle ROMX
auto errorTooLarge = [&name]() {
error("\"%s\" has more than 65536 banks", name); // LCOV_EXCL_LINE
};
static constexpr off_t NB_BANKS_LIMIT = 0x10000;
static_assert(NB_BANKS_LIMIT * BANK_SIZE <= SSIZE_MAX, "Max input file size too large for OS");
if (input == output) { if (input == output) {
if (fileSize >= 0x10000 * BANK_SIZE) { if (fileSize >= NB_BANKS_LIMIT * BANK_SIZE) {
error("\"%s\" has more than 65536 banks", name); return errorTooLarge(); // LCOV_EXCL_LINE
return;
} }
// This should be guaranteed from the size cap...
static_assert(0x10000 * BANK_SIZE <= SSIZE_MAX, "Max input file size too large for OS");
// Compute number of banks and ROMX len from file size // Compute number of banks and ROMX len from file size
nbBanks = (fileSize + (BANK_SIZE - 1)) / BANK_SIZE; // ceil(fileSize / BANK_SIZE) nbBanks = (fileSize + (BANK_SIZE - 1)) / BANK_SIZE; // ceil(fileSize / BANK_SIZE)
totalRomxLen = fileSize >= BANK_SIZE ? fileSize - BANK_SIZE : 0; totalRomxLen = fileSize >= BANK_SIZE ? fileSize - BANK_SIZE : 0;
@@ -258,19 +259,13 @@ static void
for (;;) { for (;;) {
romx.resize(nbBanks * BANK_SIZE); romx.resize(nbBanks * BANK_SIZE);
ssize_t bankLen = readBytes(input, &romx[(nbBanks - 1) * BANK_SIZE], BANK_SIZE); ssize_t bankLen = readBytes(input, &romx[(nbBanks - 1) * BANK_SIZE], BANK_SIZE);
// Update bank count, ONLY IF at least one byte was read // Update bank count, ONLY IF at least one byte was read
if (bankLen) { if (bankLen) {
// We're going to read another bank, check that it won't be too much // We're going to read another bank, check that it won't be too much
static_assert( if (nbBanks == NB_BANKS_LIMIT) {
0x10000 * BANK_SIZE <= SSIZE_MAX, "Max input file size too large for OS" return errorTooLarge(); // LCOV_EXCL_LINE
);
if (nbBanks == 0x10000) {
error("\"%s\" has more than 65536 banks", name);
return;
} }
++nbBanks; ++nbBanks;
// Update global checksum, too // Update global checksum, too
for (uint16_t i = 0; i < bankLen; ++i) { for (uint16_t i = 0; i < bankLen; ++i) {
globalSum += romx[totalRomxLen + i]; globalSum += romx[totalRomxLen + i];
@@ -341,6 +336,7 @@ static void
// Pipes have already read ROMX and updated globalSum, but not regular files // Pipes have already read ROMX and updated globalSum, but not regular files
if (input == output) { if (input == output) {
for (;;) { for (;;) {
uint8_t bank[BANK_SIZE];
ssize_t bankLen = readBytes(input, bank, sizeof(bank)); ssize_t bankLen = readBytes(input, bank, sizeof(bank));
for (uint16_t i = 0; i < bankLen; ++i) { for (uint16_t i = 0; i < bankLen; ++i) {
@@ -432,8 +428,9 @@ static void
// LCOV_EXCL_STOP // LCOV_EXCL_STOP
} }
} }
uint8_t bank[BANK_SIZE];
memset(bank, options.padValue, sizeof(bank)); memset(bank, options.padValue, sizeof(bank));
size_t len = (nbBanks - 1) * BANK_SIZE - totalRomxLen; // Don't count ROM0! size_t len = (nbBanks - 1) * sizeof(bank) - totalRomxLen; // Don't count ROM0!
while (len) { while (len) {
static_assert(sizeof(bank) <= SSIZE_MAX, "Bank too large for reading"); static_assert(sizeof(bank) <= SSIZE_MAX, "Bank too large for reading");
@@ -470,8 +467,10 @@ bool fix_ProcessFile(char const *name, char const *outputName) {
} else { } else {
output = open(outputName, O_WRONLY | O_BINARY | O_CREAT, 0600); output = open(outputName, O_WRONLY | O_BINARY | O_CREAT, 0600);
if (output == -1) { if (output == -1) {
// LCOV_EXCL_START
error("Failed to open \"%s\" for writing: %s", outputName, strerror(errno)); error("Failed to open \"%s\" for writing: %s", outputName, strerror(errno));
return true; return true;
// LCOV_EXCL_STOP
} }
openedOutput = true; openedOutput = true;
} }

View File

@@ -122,7 +122,9 @@ static void initLogo() {
logoFile = stdin; logoFile = stdin;
} }
if (!logoFile) { if (!logoFile) {
// LCOV_EXCL_START
fatal("Failed to open \"%s\" for reading: %s", options.logoFilename, strerror(errno)); fatal("Failed to open \"%s\" for reading: %s", options.logoFilename, strerror(errno));
// LCOV_EXCL_STOP
} }
Defer closeLogo{[&] { fclose(logoFile); }}; Defer closeLogo{[&] { fclose(logoFile); }};

View File

@@ -98,10 +98,6 @@ bool mbc_HasRAM(MbcType type) {
return search != mbcData.end() && search->second.second; return search != mbcData.end() && search->second.second;
} }
static void skipBlankSpace(char const *&ptr) {
ptr += strspn(ptr, " \t");
}
static void skipMBCSpace(char const *&ptr) { static void skipMBCSpace(char const *&ptr) {
ptr += strspn(ptr, " \t_"); ptr += strspn(ptr, " \t_");
} }
@@ -115,16 +111,6 @@ static char normalizeMBCChar(char c) {
return c; return c;
} }
static bool readMBCSlice(char const *&name, char const *expected) {
while (*expected) {
// If `name` is too short, the character will be '\0' and this will return `false`
if (normalizeMBCChar(*name++) != *expected++) {
return false;
}
}
return true;
}
[[noreturn]] [[noreturn]]
static void fatalUnknownMBC(char const *name) { static void fatalUnknownMBC(char const *name) {
fatal("Unknown MBC \"%s\"\n%s", name, acceptedMBCNames); fatal("Unknown MBC \"%s\"\n%s", name, acceptedMBCNames);
@@ -136,8 +122,7 @@ static void fatalWrongMBCFeatures(char const *name) {
} }
MbcType mbc_ParseName(char const *name, uint8_t &tpp1Major, uint8_t &tpp1Minor) { MbcType mbc_ParseName(char const *name, uint8_t &tpp1Major, uint8_t &tpp1Minor) {
char const *ptr = name; char const *ptr = name + strspn(name, " \t"); // Skip leading blank space
skipBlankSpace(ptr); // Trim off leading blank space
if (!strcasecmp(ptr, "help") || !strcasecmp(ptr, "list")) { if (!strcasecmp(ptr, "help") || !strcasecmp(ptr, "list")) {
puts(acceptedMBCNames); // Outputs to stdout and appends a newline puts(acceptedMBCNames); // Outputs to stdout and appends a newline
@@ -156,14 +141,16 @@ MbcType mbc_ParseName(char const *name, uint8_t &tpp1Major, uint8_t &tpp1Minor)
} }
// Begin by reading the MBC type: // Begin by reading the MBC type:
uint16_t mbc; uint16_t mbc = UINT16_MAX;
#define tryReadSlice(expected) \ auto tryReadSlice = [&ptr, &name](char const *expected) {
do { \ while (*expected) {
if (!readMBCSlice(ptr, expected)) { \ // If `name` is too short, the character will be '\0' and this will return `false`
fatalUnknownMBC(name); \ if (normalizeMBCChar(*ptr++) != *expected++) {
} \ fatalUnknownMBC(name);
} while (0) }
}
};
switch (*ptr++) { switch (*ptr++) {
case 'R': // ROM / ROM_ONLY case 'R': // ROM / ROM_ONLY
@@ -183,13 +170,7 @@ MbcType mbc_ParseName(char const *name, uint8_t &tpp1Major, uint8_t &tpp1Minor)
switch (*ptr++) { switch (*ptr++) {
case 'B': case 'B':
case 'b': case 'b':
switch (*ptr++) { tryReadSlice("C");
case 'C':
case 'c':
break;
default:
fatalUnknownMBC(name);
}
switch (*ptr++) { switch (*ptr++) {
case '1': case '1':
mbc = MBC1; mbc = MBC1;
@@ -209,8 +190,6 @@ MbcType mbc_ParseName(char const *name, uint8_t &tpp1Major, uint8_t &tpp1Minor)
case '7': case '7':
mbc = MBC7_SENSOR_RUMBLE_RAM_BATTERY; mbc = MBC7_SENSOR_RUMBLE_RAM_BATTERY;
break; break;
default:
fatalUnknownMBC(name);
} }
break; break;
case 'M': case 'M':
@@ -218,8 +197,6 @@ MbcType mbc_ParseName(char const *name, uint8_t &tpp1Major, uint8_t &tpp1Minor)
tryReadSlice("M01"); tryReadSlice("M01");
mbc = MMM01; mbc = MMM01;
break; break;
default:
fatalUnknownMBC(name);
} }
break; break;
@@ -242,7 +219,7 @@ MbcType mbc_ParseName(char const *name, uint8_t &tpp1Major, uint8_t &tpp1Minor)
tryReadSlice("MA5"); tryReadSlice("MA5");
mbc = BANDAI_TAMA5; mbc = BANDAI_TAMA5;
break; break;
case 'P': { case 'P':
tryReadSlice("P1"); tryReadSlice("P1");
// Parse version // Parse version
skipMBCSpace(ptr); skipMBCSpace(ptr);
@@ -266,9 +243,6 @@ MbcType mbc_ParseName(char const *name, uint8_t &tpp1Major, uint8_t &tpp1Minor)
mbc = TPP1; mbc = TPP1;
break; break;
} }
default:
fatalUnknownMBC(name);
}
break; break;
case 'H': // HuC{1, 3} case 'H': // HuC{1, 3}
@@ -281,12 +255,11 @@ MbcType mbc_ParseName(char const *name, uint8_t &tpp1Major, uint8_t &tpp1Minor)
case '3': case '3':
mbc = HUC3; mbc = HUC3;
break; break;
default:
fatalUnknownMBC(name);
} }
break; break;
}
default: if (mbc == UINT16_MAX) {
fatalUnknownMBC(name); fatalUnknownMBC(name);
} }
@@ -301,18 +274,10 @@ MbcType mbc_ParseName(char const *name, uint8_t &tpp1Major, uint8_t &tpp1Minor)
static constexpr uint8_t MULTIRUMBLE = 1 << 2; static constexpr uint8_t MULTIRUMBLE = 1 << 2;
// clang-format on // clang-format on
for (;;) { while (*ptr) {
skipBlankSpace(ptr); // Trim off trailing blank space
// If done, start processing "features"
if (!*ptr) {
break;
}
// We expect a '+' at this point // We expect a '+' at this point
skipMBCSpace(ptr); skipMBCSpace(ptr);
if (*ptr++ != '+') { tryReadSlice("+");
fatalUnknownMBC(name);
}
skipMBCSpace(ptr); skipMBCSpace(ptr);
switch (*ptr++) { switch (*ptr++) {
@@ -341,8 +306,6 @@ MbcType mbc_ParseName(char const *name, uint8_t &tpp1Major, uint8_t &tpp1Minor)
tryReadSlice("M"); tryReadSlice("M");
features |= RAM; features |= RAM;
break; break;
default:
fatalUnknownMBC(name);
} }
break; break;
@@ -357,12 +320,8 @@ MbcType mbc_ParseName(char const *name, uint8_t &tpp1Major, uint8_t &tpp1Minor)
tryReadSlice("IMER"); tryReadSlice("IMER");
features |= TIMER; features |= TIMER;
break; break;
default:
fatalUnknownMBC(name);
} }
} }
#undef tryReadSlice
switch (mbc) { switch (mbc) {
case ROM: case ROM:
@@ -459,37 +418,34 @@ MbcType mbc_ParseName(char const *name, uint8_t &tpp1Major, uint8_t &tpp1Minor)
} }
break; break;
case TPP1: case TPP1: {
// clang-format off: vertically align values
static constexpr uint8_t BATTERY_TPP1 = 1 << 3;
static constexpr uint8_t TIMER_TPP1 = 1 << 2;
static constexpr uint8_t MULTIRUMBLE_TPP1 = 1 << 1;
static constexpr uint8_t RUMBLE_TPP1 = 1 << 0;
// clang-format on
if (features & RAM) { if (features & RAM) {
warning(WARNING_MBC, "TPP1 requests RAM implicitly if given a non-zero RAM size"); warning(WARNING_MBC, "TPP1 requests RAM implicitly if given a non-zero RAM size");
} }
if (features & BATTERY) { if (features & BATTERY) {
mbc |= 0x08; mbc |= BATTERY_TPP1;
} }
if (features & TIMER) { if (features & TIMER) {
mbc |= 0x04; mbc |= TIMER_TPP1;
}
if (features & MULTIRUMBLE) {
mbc |= 0x03; // Also set the rumble flag
} }
if (features & RUMBLE) { if (features & RUMBLE) {
mbc |= 0x01; mbc |= RUMBLE_TPP1;
} }
if (features & SENSOR) { if (features & SENSOR) {
fatalWrongMBCFeatures(name); fatalWrongMBCFeatures(name);
} }
// Multiple rumble speeds imply rumble if (features & MULTIRUMBLE) {
if (mbc & 0x01) { mbc |= MULTIRUMBLE_TPP1 | RUMBLE_TPP1; // Multiple rumble speeds imply rumble
assume(mbc & 0x02);
} }
break; break;
} }
skipBlankSpace(ptr); // Trim off trailing blank space
// If there is still something left, error out
if (*ptr) {
fatalUnknownMBC(name);
} }
return static_cast<MbcType>(mbc); return static_cast<MbcType>(mbc);

View File

@@ -0,0 +1,23 @@
FATAL: Features incompatible with MBC ("HUC1")
Accepted MBC names:
ROM ($00) [aka ROM_ONLY]
MBC1 ($01), MBC1+RAM ($02), MBC1+RAM+BATTERY ($03)
MBC2 ($05), MBC2+BATTERY ($06)
ROM+RAM ($08) [deprecated], ROM+RAM+BATTERY ($09) [deprecated]
MMM01 ($0B), MMM01+RAM ($0C), MMM01+RAM+BATTERY ($0D)
MBC3+TIMER+BATTERY ($0F), MBC3+TIMER+RAM+BATTERY ($10)
MBC3 ($11), MBC3+RAM ($12), MBC3+RAM+BATTERY ($13)
MBC5 ($19), MBC5+RAM ($1A), MBC5+RAM+BATTERY ($1B)
MBC5+RUMBLE ($1C), MBC5+RUMBLE+RAM ($1D), MBC5+RUMBLE+RAM+BATTERY ($1E)
MBC6 ($20)
MBC7+SENSOR+RUMBLE+RAM+BATTERY ($22)
POCKET_CAMERA ($FC)
BANDAI_TAMA5 ($FD) [aka TAMA5]
HUC3 ($FE)
HUC1+RAM+BATTERY ($FF)
TPP1_1.0, TPP1_1.0+RUMBLE, TPP1_1.0+MULTIRUMBLE, TPP1_1.0+TIMER,
TPP1_1.0+TIMER+RUMBLE, TPP1_1.0+TIMER+MULTIRUMBLE, TPP1_1.0+BATTERY,
TPP1_1.0+BATTERY+RUMBLE, TPP1_1.0+BATTERY+MULTIRUMBLE,
TPP1_1.0+BATTERY+TIMER, TPP1_1.0+BATTERY+TIMER+RUMBLE,
TPP1_1.0+BATTERY+TIMER+MULTIRUMBLE

View File

@@ -0,0 +1 @@
-m HUC1

23
test/fix/bad-mbc-name.err Normal file
View File

@@ -0,0 +1,23 @@
FATAL: Unknown MBC "MBC9"
Accepted MBC names:
ROM ($00) [aka ROM_ONLY]
MBC1 ($01), MBC1+RAM ($02), MBC1+RAM+BATTERY ($03)
MBC2 ($05), MBC2+BATTERY ($06)
ROM+RAM ($08) [deprecated], ROM+RAM+BATTERY ($09) [deprecated]
MMM01 ($0B), MMM01+RAM ($0C), MMM01+RAM+BATTERY ($0D)
MBC3+TIMER+BATTERY ($0F), MBC3+TIMER+RAM+BATTERY ($10)
MBC3 ($11), MBC3+RAM ($12), MBC3+RAM+BATTERY ($13)
MBC5 ($19), MBC5+RAM ($1A), MBC5+RAM+BATTERY ($1B)
MBC5+RUMBLE ($1C), MBC5+RUMBLE+RAM ($1D), MBC5+RUMBLE+RAM+BATTERY ($1E)
MBC6 ($20)
MBC7+SENSOR+RUMBLE+RAM+BATTERY ($22)
POCKET_CAMERA ($FC)
BANDAI_TAMA5 ($FD) [aka TAMA5]
HUC3 ($FE)
HUC1+RAM+BATTERY ($FF)
TPP1_1.0, TPP1_1.0+RUMBLE, TPP1_1.0+MULTIRUMBLE, TPP1_1.0+TIMER,
TPP1_1.0+TIMER+RUMBLE, TPP1_1.0+TIMER+MULTIRUMBLE, TPP1_1.0+BATTERY,
TPP1_1.0+BATTERY+RUMBLE, TPP1_1.0+BATTERY+MULTIRUMBLE,
TPP1_1.0+BATTERY+TIMER, TPP1_1.0+BATTERY+TIMER+RUMBLE,
TPP1_1.0+BATTERY+TIMER+MULTIRUMBLE

View File

@@ -0,0 +1 @@
-m MBC9

View File

@@ -0,0 +1,23 @@
FATAL: Unknown MBC "123abc"
Accepted MBC names:
ROM ($00) [aka ROM_ONLY]
MBC1 ($01), MBC1+RAM ($02), MBC1+RAM+BATTERY ($03)
MBC2 ($05), MBC2+BATTERY ($06)
ROM+RAM ($08) [deprecated], ROM+RAM+BATTERY ($09) [deprecated]
MMM01 ($0B), MMM01+RAM ($0C), MMM01+RAM+BATTERY ($0D)
MBC3+TIMER+BATTERY ($0F), MBC3+TIMER+RAM+BATTERY ($10)
MBC3 ($11), MBC3+RAM ($12), MBC3+RAM+BATTERY ($13)
MBC5 ($19), MBC5+RAM ($1A), MBC5+RAM+BATTERY ($1B)
MBC5+RUMBLE ($1C), MBC5+RUMBLE+RAM ($1D), MBC5+RUMBLE+RAM+BATTERY ($1E)
MBC6 ($20)
MBC7+SENSOR+RUMBLE+RAM+BATTERY ($22)
POCKET_CAMERA ($FC)
BANDAI_TAMA5 ($FD) [aka TAMA5]
HUC3 ($FE)
HUC1+RAM+BATTERY ($FF)
TPP1_1.0, TPP1_1.0+RUMBLE, TPP1_1.0+MULTIRUMBLE, TPP1_1.0+TIMER,
TPP1_1.0+TIMER+RUMBLE, TPP1_1.0+TIMER+MULTIRUMBLE, TPP1_1.0+BATTERY,
TPP1_1.0+BATTERY+RUMBLE, TPP1_1.0+BATTERY+MULTIRUMBLE,
TPP1_1.0+BATTERY+TIMER, TPP1_1.0+BATTERY+TIMER+RUMBLE,
TPP1_1.0+BATTERY+TIMER+MULTIRUMBLE

View File

@@ -0,0 +1 @@
-m 123abc

View File

@@ -0,0 +1 @@
FATAL: Specified MBC ID out of range 0-255: "999"

View File

@@ -0,0 +1 @@
-m 999

View File

@@ -0,0 +1,23 @@
FATAL: Features incompatible with MBC ("MBC2+TIMER")
Accepted MBC names:
ROM ($00) [aka ROM_ONLY]
MBC1 ($01), MBC1+RAM ($02), MBC1+RAM+BATTERY ($03)
MBC2 ($05), MBC2+BATTERY ($06)
ROM+RAM ($08) [deprecated], ROM+RAM+BATTERY ($09) [deprecated]
MMM01 ($0B), MMM01+RAM ($0C), MMM01+RAM+BATTERY ($0D)
MBC3+TIMER+BATTERY ($0F), MBC3+TIMER+RAM+BATTERY ($10)
MBC3 ($11), MBC3+RAM ($12), MBC3+RAM+BATTERY ($13)
MBC5 ($19), MBC5+RAM ($1A), MBC5+RAM+BATTERY ($1B)
MBC5+RUMBLE ($1C), MBC5+RUMBLE+RAM ($1D), MBC5+RUMBLE+RAM+BATTERY ($1E)
MBC6 ($20)
MBC7+SENSOR+RUMBLE+RAM+BATTERY ($22)
POCKET_CAMERA ($FC)
BANDAI_TAMA5 ($FD) [aka TAMA5]
HUC3 ($FE)
HUC1+RAM+BATTERY ($FF)
TPP1_1.0, TPP1_1.0+RUMBLE, TPP1_1.0+MULTIRUMBLE, TPP1_1.0+TIMER,
TPP1_1.0+TIMER+RUMBLE, TPP1_1.0+TIMER+MULTIRUMBLE, TPP1_1.0+BATTERY,
TPP1_1.0+BATTERY+RUMBLE, TPP1_1.0+BATTERY+MULTIRUMBLE,
TPP1_1.0+BATTERY+TIMER, TPP1_1.0+BATTERY+TIMER+RUMBLE,
TPP1_1.0+BATTERY+TIMER+MULTIRUMBLE

View File

@@ -0,0 +1 @@
-m MBC2+TIMER

View File

@@ -0,0 +1,23 @@
FATAL: Features incompatible with MBC ("MBC3+TIMER+RUMBLE+BATTERY")
Accepted MBC names:
ROM ($00) [aka ROM_ONLY]
MBC1 ($01), MBC1+RAM ($02), MBC1+RAM+BATTERY ($03)
MBC2 ($05), MBC2+BATTERY ($06)
ROM+RAM ($08) [deprecated], ROM+RAM+BATTERY ($09) [deprecated]
MMM01 ($0B), MMM01+RAM ($0C), MMM01+RAM+BATTERY ($0D)
MBC3+TIMER+BATTERY ($0F), MBC3+TIMER+RAM+BATTERY ($10)
MBC3 ($11), MBC3+RAM ($12), MBC3+RAM+BATTERY ($13)
MBC5 ($19), MBC5+RAM ($1A), MBC5+RAM+BATTERY ($1B)
MBC5+RUMBLE ($1C), MBC5+RUMBLE+RAM ($1D), MBC5+RUMBLE+RAM+BATTERY ($1E)
MBC6 ($20)
MBC7+SENSOR+RUMBLE+RAM+BATTERY ($22)
POCKET_CAMERA ($FC)
BANDAI_TAMA5 ($FD) [aka TAMA5]
HUC3 ($FE)
HUC1+RAM+BATTERY ($FF)
TPP1_1.0, TPP1_1.0+RUMBLE, TPP1_1.0+MULTIRUMBLE, TPP1_1.0+TIMER,
TPP1_1.0+TIMER+RUMBLE, TPP1_1.0+TIMER+MULTIRUMBLE, TPP1_1.0+BATTERY,
TPP1_1.0+BATTERY+RUMBLE, TPP1_1.0+BATTERY+MULTIRUMBLE,
TPP1_1.0+BATTERY+TIMER, TPP1_1.0+BATTERY+TIMER+RUMBLE,
TPP1_1.0+BATTERY+TIMER+MULTIRUMBLE

View File

@@ -0,0 +1 @@
-m MBC3+TIMER+RUMBLE+BATTERY

View File

@@ -0,0 +1,23 @@
FATAL: Features incompatible with MBC ("MBC5+RUMBLE+BATTERY")
Accepted MBC names:
ROM ($00) [aka ROM_ONLY]
MBC1 ($01), MBC1+RAM ($02), MBC1+RAM+BATTERY ($03)
MBC2 ($05), MBC2+BATTERY ($06)
ROM+RAM ($08) [deprecated], ROM+RAM+BATTERY ($09) [deprecated]
MMM01 ($0B), MMM01+RAM ($0C), MMM01+RAM+BATTERY ($0D)
MBC3+TIMER+BATTERY ($0F), MBC3+TIMER+RAM+BATTERY ($10)
MBC3 ($11), MBC3+RAM ($12), MBC3+RAM+BATTERY ($13)
MBC5 ($19), MBC5+RAM ($1A), MBC5+RAM+BATTERY ($1B)
MBC5+RUMBLE ($1C), MBC5+RUMBLE+RAM ($1D), MBC5+RUMBLE+RAM+BATTERY ($1E)
MBC6 ($20)
MBC7+SENSOR+RUMBLE+RAM+BATTERY ($22)
POCKET_CAMERA ($FC)
BANDAI_TAMA5 ($FD) [aka TAMA5]
HUC3 ($FE)
HUC1+RAM+BATTERY ($FF)
TPP1_1.0, TPP1_1.0+RUMBLE, TPP1_1.0+MULTIRUMBLE, TPP1_1.0+TIMER,
TPP1_1.0+TIMER+RUMBLE, TPP1_1.0+TIMER+MULTIRUMBLE, TPP1_1.0+BATTERY,
TPP1_1.0+BATTERY+RUMBLE, TPP1_1.0+BATTERY+MULTIRUMBLE,
TPP1_1.0+BATTERY+TIMER, TPP1_1.0+BATTERY+TIMER+RUMBLE,
TPP1_1.0+BATTERY+TIMER+MULTIRUMBLE

View File

@@ -0,0 +1 @@
-m MBC5+RUMBLE+BATTERY

View File

@@ -0,0 +1,23 @@
FATAL: Features incompatible with MBC ("MBC6+RAM")
Accepted MBC names:
ROM ($00) [aka ROM_ONLY]
MBC1 ($01), MBC1+RAM ($02), MBC1+RAM+BATTERY ($03)
MBC2 ($05), MBC2+BATTERY ($06)
ROM+RAM ($08) [deprecated], ROM+RAM+BATTERY ($09) [deprecated]
MMM01 ($0B), MMM01+RAM ($0C), MMM01+RAM+BATTERY ($0D)
MBC3+TIMER+BATTERY ($0F), MBC3+TIMER+RAM+BATTERY ($10)
MBC3 ($11), MBC3+RAM ($12), MBC3+RAM+BATTERY ($13)
MBC5 ($19), MBC5+RAM ($1A), MBC5+RAM+BATTERY ($1B)
MBC5+RUMBLE ($1C), MBC5+RUMBLE+RAM ($1D), MBC5+RUMBLE+RAM+BATTERY ($1E)
MBC6 ($20)
MBC7+SENSOR+RUMBLE+RAM+BATTERY ($22)
POCKET_CAMERA ($FC)
BANDAI_TAMA5 ($FD) [aka TAMA5]
HUC3 ($FE)
HUC1+RAM+BATTERY ($FF)
TPP1_1.0, TPP1_1.0+RUMBLE, TPP1_1.0+MULTIRUMBLE, TPP1_1.0+TIMER,
TPP1_1.0+TIMER+RUMBLE, TPP1_1.0+TIMER+MULTIRUMBLE, TPP1_1.0+BATTERY,
TPP1_1.0+BATTERY+RUMBLE, TPP1_1.0+BATTERY+MULTIRUMBLE,
TPP1_1.0+BATTERY+TIMER, TPP1_1.0+BATTERY+TIMER+RUMBLE,
TPP1_1.0+BATTERY+TIMER+MULTIRUMBLE

View File

@@ -0,0 +1 @@
-m MBC6+RAM

View File

@@ -0,0 +1,23 @@
FATAL: Features incompatible with MBC ("MBC7+TIMER")
Accepted MBC names:
ROM ($00) [aka ROM_ONLY]
MBC1 ($01), MBC1+RAM ($02), MBC1+RAM+BATTERY ($03)
MBC2 ($05), MBC2+BATTERY ($06)
ROM+RAM ($08) [deprecated], ROM+RAM+BATTERY ($09) [deprecated]
MMM01 ($0B), MMM01+RAM ($0C), MMM01+RAM+BATTERY ($0D)
MBC3+TIMER+BATTERY ($0F), MBC3+TIMER+RAM+BATTERY ($10)
MBC3 ($11), MBC3+RAM ($12), MBC3+RAM+BATTERY ($13)
MBC5 ($19), MBC5+RAM ($1A), MBC5+RAM+BATTERY ($1B)
MBC5+RUMBLE ($1C), MBC5+RUMBLE+RAM ($1D), MBC5+RUMBLE+RAM+BATTERY ($1E)
MBC6 ($20)
MBC7+SENSOR+RUMBLE+RAM+BATTERY ($22)
POCKET_CAMERA ($FC)
BANDAI_TAMA5 ($FD) [aka TAMA5]
HUC3 ($FE)
HUC1+RAM+BATTERY ($FF)
TPP1_1.0, TPP1_1.0+RUMBLE, TPP1_1.0+MULTIRUMBLE, TPP1_1.0+TIMER,
TPP1_1.0+TIMER+RUMBLE, TPP1_1.0+TIMER+MULTIRUMBLE, TPP1_1.0+BATTERY,
TPP1_1.0+BATTERY+RUMBLE, TPP1_1.0+BATTERY+MULTIRUMBLE,
TPP1_1.0+BATTERY+TIMER, TPP1_1.0+BATTERY+TIMER+RUMBLE,
TPP1_1.0+BATTERY+TIMER+MULTIRUMBLE

View File

@@ -0,0 +1 @@
-m MBC7+TIMER

View File

@@ -0,0 +1,23 @@
FATAL: Features incompatible with MBC ("TPP1_1.0+BATTERY+TIMER+SENSOR")
Accepted MBC names:
ROM ($00) [aka ROM_ONLY]
MBC1 ($01), MBC1+RAM ($02), MBC1+RAM+BATTERY ($03)
MBC2 ($05), MBC2+BATTERY ($06)
ROM+RAM ($08) [deprecated], ROM+RAM+BATTERY ($09) [deprecated]
MMM01 ($0B), MMM01+RAM ($0C), MMM01+RAM+BATTERY ($0D)
MBC3+TIMER+BATTERY ($0F), MBC3+TIMER+RAM+BATTERY ($10)
MBC3 ($11), MBC3+RAM ($12), MBC3+RAM+BATTERY ($13)
MBC5 ($19), MBC5+RAM ($1A), MBC5+RAM+BATTERY ($1B)
MBC5+RUMBLE ($1C), MBC5+RUMBLE+RAM ($1D), MBC5+RUMBLE+RAM+BATTERY ($1E)
MBC6 ($20)
MBC7+SENSOR+RUMBLE+RAM+BATTERY ($22)
POCKET_CAMERA ($FC)
BANDAI_TAMA5 ($FD) [aka TAMA5]
HUC3 ($FE)
HUC1+RAM+BATTERY ($FF)
TPP1_1.0, TPP1_1.0+RUMBLE, TPP1_1.0+MULTIRUMBLE, TPP1_1.0+TIMER,
TPP1_1.0+TIMER+RUMBLE, TPP1_1.0+TIMER+MULTIRUMBLE, TPP1_1.0+BATTERY,
TPP1_1.0+BATTERY+RUMBLE, TPP1_1.0+BATTERY+MULTIRUMBLE,
TPP1_1.0+BATTERY+TIMER, TPP1_1.0+BATTERY+TIMER+RUMBLE,
TPP1_1.0+BATTERY+TIMER+MULTIRUMBLE

View File

@@ -0,0 +1 @@
-m TPP1_1.0+BATTERY+TIMER+SENSOR -r 8

View File

@@ -0,0 +1 @@
warning: "MBC3+TIMER" implies "BATTERY" [-Wmbc]

View File

@@ -0,0 +1 @@
-m MBC3+TIMER

BIN
test/fix/mbc-mbc3-timer.gb Normal file

Binary file not shown.

BIN
test/fix/tpp1-rumble.bin Normal file

Binary file not shown.

6
test/fix/tpp1-rumble.err Normal file
View File

@@ -0,0 +1,6 @@
warning: TPP1 requests RAM implicitly if given a non-zero RAM size [-Wmbc]
warning: Overwrote a non-zero byte in the cartridge type [-Woverwrite]
warning: Overwrote a non-zero byte in the TPP1 identification code [-Woverwrite]
warning: Overwrote a non-zero byte in the TPP1 revision number [-Woverwrite]
warning: Overwrote a non-zero byte in the RAM size [-Woverwrite]
warning: Overwrote a non-zero byte in the TPP1 feature flags [-Woverwrite]

View File

@@ -0,0 +1 @@
-m TPP1_1.0+RAM+BATTERY+TIMER+RUMBLE -r 8

BIN
test/fix/tpp1-rumble.gb Normal file

Binary file not shown.

Binary file not shown.

View File

@@ -0,0 +1,2 @@
error: Overwrote a non-zero byte in the mask ROM version number [-Werror=overwrite]
Fixing "<filename>" failed with 1 error

View File

@@ -0,0 +1 @@
-Werror=overwrite -n 11

Binary file not shown.