Add TPP1 support

Fixes #846
This commit is contained in:
ISSOtm
2021-05-01 14:40:24 +02:00
committed by Eldred Habert
parent d360d03403
commit 6e1a5dcc9d
21 changed files with 363 additions and 31 deletions

View File

@@ -25,7 +25,7 @@
#include "platform.h"
#include "version.h"
#define UNSPECIFIED 0x100 // May not be in byte range
#define UNSPECIFIED 0x200 // Should not be in byte range
#define BANK_SIZE 0x4000
@@ -79,6 +79,20 @@ static void printUsage(void)
stderr);
}
static uint8_t nbErrors;
static format_(printf, 1, 2) void report(char const *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
if (nbErrors != UINT8_MAX)
nbErrors++;
}
enum MbcType {
ROM = 0x00,
ROM_RAM = 0x08,
@@ -120,6 +134,28 @@ enum MbcType {
HUC1_RAM_BATTERY = 0xFF,
// "Extended" values (still valid, but not directly actionable)
// A high byte of 0x01 means TPP1, the low byte is the requested features
// This does not include SRAM, which is instead implied by a non-zero SRAM size
// Note: Multiple rumble speeds imply rumble
TPP1 = 0x100,
TPP1_RUMBLE = 0x101,
TPP1_MULTIRUMBLE = 0x102, // Should not be possible
TPP1_MULTIRUMBLE_RUMBLE = 0x103,
TPP1_RTC = 0x104,
TPP1_RTC_RUMBLE = 0x105,
TPP1_RTC_MULTIRUMBLE = 0x106, // Should not be possible
TPP1_RTC_MULTIRUMBLE_RUMBLE = 0x107,
TPP1_BATTERY = 0x108,
TPP1_BATTERY_RUMBLE = 0x109,
TPP1_BATTERY_MULTIRUMBLE = 0x10a, // Should not be possible
TPP1_BATTERY_MULTIRUMBLE_RUMBLE = 0x10b,
TPP1_BATTERY_RTC = 0x10c,
TPP1_BATTERY_RTC_RUMBLE = 0x10d,
TPP1_BATTERY_RTC_MULTIRUMBLE = 0x10e, // Should not be possible
TPP1_BATTERY_RTC_MULTIRUMBLE_RUMBLE = 0x10f,
// Error values
MBC_NONE = UNSPECIFIED, // No MBC specified, do not act on it
MBC_BAD, // Specified MBC does not exist / syntax error
@@ -144,8 +180,16 @@ static void printAcceptedMBCNames(void)
fputs("\tBANDAI_TAMA5 ($FD)\n", stderr);
fputs("\tHUC3 ($FE)\n", stderr);
fputs("\tHUC1+RAM+BATTERY ($FF)\n", stderr);
fputs("\n\tTPP1_1.0, TPP1_1.0+RUMBLE, TPP1_1.0+MULTIRUMBLE, TPP1_1.0+RTC,\n", stderr);
fputs("\tTPP1_1.0+RTC+RUMBLE, TPP1_1.0+RTC+MULTIRUMBLE, TPP1_1.0+BATTERY,\n", stderr);
fputs("\tTPP1_1.0+BATTERY+RUMBLE, TPP1_1.0+BATTERY+MULTIRUMBLE,\n", stderr);
fputs("\tTPP1_1.0+BATTERY+RTC, TPP1_1.0+BATTERY+RTC+RUMBLE,\n", stderr);
fputs("\tTPP1_1.0+BATTERY+RTC+MULTIRUMBLE\n", stderr);
}
static uint8_t tpp1Rev[2];
/**
* @return False on failure
*/
@@ -279,10 +323,50 @@ do { \
mbc = BANDAI_TAMA5;
break;
case 'T': // TAMA5
case 'T': // TAMA5 / TPP1
case 't':
tryReadSlice("AMA5");
mbc = BANDAI_TAMA5;
switch (*ptr++) {
case 'A':
tryReadSlice("MA5");
mbc = BANDAI_TAMA5;
break;
case 'P':
tryReadSlice("P1");
// Parse version
while (*ptr == ' ' || *ptr == '_')
ptr++;
// Major
char *endptr;
unsigned long val = strtoul(ptr, &endptr, 10);
if (endptr == ptr) {
report("error: Failed to parse TPP1 major revision number\n");
return MBC_BAD;
}
ptr = endptr;
if (val != 1) {
report("error: RGBFIX only supports TPP1 versions 1.0\n");
return MBC_BAD;
}
tpp1Rev[0] = val;
tryReadSlice(".");
// Minor
val = strtoul(ptr, &endptr, 10);
if (endptr == ptr) {
report("error: Failed to parse TPP1 minor revision number\n");
return MBC_BAD;
}
ptr = endptr;
if (val > 0xFF) {
report("error: TPP1 minor revision number must be 8-bit\n");
return MBC_BAD;
}
tpp1Rev[1] = val;
mbc = TPP1;
break;
default:
return MBC_BAD;
}
break;
case 'H': // HuC{1, 3}
@@ -311,6 +395,7 @@ do { \
#define TIMER 0x20
#define RUMBLE 0x10
#define SENSOR 0x08
#define MULTIRUMBLE 0x04
for (;;) {
// Trim off trailing whitespace
@@ -334,6 +419,12 @@ do { \
features |= BATTERY;
break;
case 'M':
case 'm':
tryReadSlice("ULTIRUMBLE");
features |= MULTIRUMBLE;
break;
case 'R': // RAM or RUMBLE
case 'r':
switch (*ptr++) {
@@ -455,6 +546,22 @@ do { \
if (features != (RAM | BATTERY)) // HuC1 expects RAM+BATTERY
return MBC_WRONG_FEATURES;
break;
case TPP1:
if (features & RAM)
fprintf(stderr,
"warning: TPP1 requests RAM implicitly if given a non-zero RAM size");
if (features & BATTERY)
mbc |= 0x08;
if (features & TIMER)
mbc |= 0x04;
if (features & MULTIRUMBLE)
mbc |= 0x03; // Also set the rumble flag
if (features & RUMBLE)
mbc |= 0x01;
if (features & SENSOR)
return MBC_WRONG_FEATURES;
break;
}
// Trim off trailing whitespace
@@ -528,6 +635,34 @@ static char const *mbcName(enum MbcType type)
return "HUC3";
case HUC1_RAM_BATTERY:
return "HUC1+RAM+BATTERY";
case TPP1:
return "TPP1";
case TPP1_RUMBLE:
return "TPP1+RUMBLE";
case TPP1_MULTIRUMBLE:
case TPP1_MULTIRUMBLE_RUMBLE:
return "TPP1+MULTIRUMBLE";
case TPP1_RTC:
return "TPP1+RTC";
case TPP1_RTC_RUMBLE:
return "TPP1+RTC+RUMBLE";
case TPP1_RTC_MULTIRUMBLE:
case TPP1_RTC_MULTIRUMBLE_RUMBLE:
return "TPP1+RTC+MULTIRUMBLE";
case TPP1_BATTERY:
return "TPP1+BATTERY";
case TPP1_BATTERY_RUMBLE:
return "TPP1+BATTERY+RUMBLE";
case TPP1_BATTERY_MULTIRUMBLE:
case TPP1_BATTERY_MULTIRUMBLE_RUMBLE:
return "TPP1+BATTERY+MULTIRUMBLE";
case TPP1_BATTERY_RTC:
return "TPP1+BATTERY+RTC";
case TPP1_BATTERY_RTC_RUMBLE:
return "TPP1+BATTERY+RTC+RUMBLE";
case TPP1_BATTERY_RTC_MULTIRUMBLE:
case TPP1_BATTERY_RTC_MULTIRUMBLE_RUMBLE:
return "TPP1+BATTERY+RTC+MULTIRUMBLE";
// Error values
case MBC_NONE:
@@ -578,25 +713,30 @@ static bool hasRAM(enum MbcType type)
case HUC3:
case HUC1_RAM_BATTERY:
return true;
// TPP1 may or may not have RAM, don't call this function for it
case TPP1:
case TPP1_RUMBLE:
case TPP1_MULTIRUMBLE:
case TPP1_MULTIRUMBLE_RUMBLE:
case TPP1_RTC:
case TPP1_RTC_RUMBLE:
case TPP1_RTC_MULTIRUMBLE:
case TPP1_RTC_MULTIRUMBLE_RUMBLE:
case TPP1_BATTERY:
case TPP1_BATTERY_RUMBLE:
case TPP1_BATTERY_MULTIRUMBLE:
case TPP1_BATTERY_MULTIRUMBLE_RUMBLE:
case TPP1_BATTERY_RTC:
case TPP1_BATTERY_RTC_RUMBLE:
case TPP1_BATTERY_RTC_MULTIRUMBLE:
case TPP1_BATTERY_RTC_MULTIRUMBLE_RUMBLE:
break;
}
unreachable_();
}
static uint8_t nbErrors;
static format_(printf, 1, 2) void report(char const *fmt, ...)
{
va_list ap;
va_start(ap, fmt);
vfprintf(stderr, fmt, ap);
va_end(ap);
if (nbErrors != UINT8_MAX)
nbErrors++;
}
static const uint8_t ninLogo[] = {
0xCE, 0xED, 0x66, 0x66, 0xCC, 0x0D, 0x00, 0x0B,
0x03, 0x73, 0x00, 0x83, 0x00, 0x0C, 0x00, 0x0D,
@@ -716,13 +856,15 @@ static void processFile(int input, int output, char const *name, off_t fileSize)
uint8_t rom0[BANK_SIZE];
ssize_t rom0Len = readBytes(input, rom0, sizeof(rom0));
// Also used as how many bytes to write back when fixing in-place
ssize_t headerSize = (cartridgeType & 0xff00) == TPP1 ? 0x154 : 0x150;
if (rom0Len == -1) {
report("FATAL: Failed to read \"%s\"'s header: %s\n", name, strerror(errno));
return;
} else if (rom0Len < 0x150) {
report("FATAL: \"%s\" too short, expected at least 336 ($150) bytes, got only %jd\n",
name, (intmax_t)rom0Len);
} else if (rom0Len < headerSize) {
report("FATAL: \"%s\" too short, expected at least %jd ($%jx) bytes, got only %jd\n",
name, (intmax_t)headerSize, (intmax_t)headerSize, (intmax_t)rom0Len);
return;
}
// Accept partial reads if the file contains at least the header
@@ -765,17 +907,46 @@ static void processFile(int input, int output, char const *name, off_t fileSize)
// If a valid MBC was specified...
if (cartridgeType < MBC_NONE) {
warnNonZero(rom0, 0x147, 1, "cartridge type");
rom0[0x147] = cartridgeType;
uint8_t byte = cartridgeType;
if ((cartridgeType & 0xff00) == TPP1) {
// Cartridge type isn't directly actionable, translate it
byte = 0xBC;
// The other TPP1 identification bytes will be written below
}
rom0[0x147] = byte;
}
if (ramSize != UNSPECIFIED) {
warnNonZero(rom0, 0x149, 1, "RAM size");
rom0[0x149] = ramSize;
}
// ROM size will be written last, after evaluating the file's size
if (!japanese) {
warnNonZero(rom0, 0x14a, 1, "destination code");
rom0[0x14a] = 0x01;
if ((cartridgeType & 0xff00) == TPP1) {
warnNonZero(rom0, 0x149, 2, "TPP1 identification code");
rom0[0x149] = 0xC1;
rom0[0x14a] = 0x65;
warnNonZero(rom0, 0x150, 2, "TPP1 revision number");
rom0[0x150] = tpp1Rev[0];
rom0[0x151] = tpp1Rev[1];
if (ramSize != UNSPECIFIED) {
warnNonZero(rom0, 0x152, 1, "RAM size");
rom0[0x152] = ramSize;
}
warnNonZero(rom0, 0x153, 1, "TPP1 feature flags");
rom0[0x153] = cartridgeType & 0xFF;
} else {
// Regular mappers
if (ramSize != UNSPECIFIED) {
warnNonZero(rom0, 0x149, 1, "RAM size");
rom0[0x149] = ramSize;
}
if (!japanese) {
warnNonZero(rom0, 0x14a, 1, "destination code");
rom0[0x14a] = 0x01;
}
}
if (oldLicensee != UNSPECIFIED) {
@@ -925,7 +1096,7 @@ static void processFile(int input, int output, char const *name, off_t fileSize)
// If modifying the file in-place, we only need to edit the header
// However, padding may have modified ROM0 (added padding), so don't in that case
if (padValue == UNSPECIFIED)
rom0Len = 0x150;
rom0Len = headerSize;
}
ssize_t writeLen = writeBytes(output, rom0, rom0Len);
@@ -1219,7 +1390,11 @@ do { \
#undef parseByte
}
if (ramSize != UNSPECIFIED && cartridgeType < UNSPECIFIED) {
if ((cartridgeType & 0xff00) == TPP1 && !japanese)
fprintf(stderr, "warning: TPP1 overwrites region flag for its identification code, ignoring `-j`\n");
// Check that RAM size is correct for "standard" mappers
if (ramSize != UNSPECIFIED && (cartridgeType & 0xff00) == 0) {
if (cartridgeType == ROM_RAM || cartridgeType == ROM_RAM_BATTERY) {
if (ramSize != 1)
fprintf(stderr, "warning: MBC \"%s\" should have 2kiB of RAM (-r 1)\n",

View File

@@ -116,6 +116,9 @@ to a given value from 0 to 0xFF.
This value may also be an MBC name.
The list of accepted names can be obtained by passing "help" as the argument.
Any amount of whitespace (space and tabs) is allowed around plus signs, and the order of "components" is free, as long as the MBC name is first.
There are special considerations to take for the TPP1 mapper; see the
.Sx TPP1
section below.
.It Fl n Ar rom_version , Fl Fl rom-version Ar rom_version
Set the ROM version
.Pq Ad 0x14C
@@ -182,6 +185,46 @@ sans global checksum:
.Pp
.D1 $ rgbfix -cjsv -k A4 -l 0x33 -m 0x1B -p 0xFF -r 3 -t SURVIVALKIDAVKE \
SurvivalKids.gbc
.Sh TPP1
TPP1 is a homebrew mapper designed as a functional superset of the common traditional MBCs, allowing larger ROM and RAM sizes combined with other hardware features.
Its specification, as well as more resources, can be found online at
.Lk https://github.com/TwitchPlaysPokemon/tpp1 .
.Ss MBC name
The MBC name for TPP1 is more complex than standard mappers.
It must be followed with the revision number, of the form
.Ql major.minor ,
where both
.Ql major
and
.Ql minor
are decimal, 8-bit integers.
There may be any amount of spaces or underscores between
.Ql TPP1
and the revision number.
.Nm
only supports 1.x revisions, and will reject everything else.
.Pp
Like other mappers, the name may be followed with a list of optional,
.Ql + Ns
-separated features; however,
.Ql RAM
should not be specified, as the TPP1 mapper implicitly requests RAM if a non-zero RAM size is specified.
Therefore,
.Nm
will ignore the
.Ql RAM
feature on a TPP1 mapper with a warning.
.Ss Special considerations
TPP1 overwrites the byte at
.Ad 0x14A ,
usually indicating the region destination
.Pq see Fl j ,
with one of its three identification bytes.
Therefore,
.Nm
will warn about and ignore
.Fl j
if used in combination with TPP1.
.Sh BUGS
Please report bugs on
.Lk https://github.com/gbdev/rgbds/issues GitHub .

BIN
test/fix/tpp1-bad-major.bin Normal file

Binary file not shown.

View File

@@ -0,0 +1,24 @@
error: Failed to parse TPP1 major revision number
error: Unknown MBC "TPP1_lol"
Accepted MBC names:
ROM ($00) [aka ROM_ONLY]
MBC1 ($02), 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)
HUC3 ($FE)
HUC1+RAM+BATTERY ($FF)
TPP1_1.0, TPP1_1.0+RUMBLE, TPP1_1.0+MULTIRUMBLE, TPP1_1.0+RTC,
TPP1_1.0+RTC+RUMBLE, TPP1_1.0+RTC+MULTIRUMBLE, TPP1_1.0+BATTERY,
TPP1_1.0+BATTERY+RUMBLE, TPP1_1.0+BATTERY+MULTIRUMBLE,
TPP1_1.0+BATTERY+RTC, TPP1_1.0+BATTERY+RTC+RUMBLE,
TPP1_1.0+BATTERY+RTC+MULTIRUMBLE

View File

@@ -0,0 +1 @@
-m TPP1_lol

BIN
test/fix/tpp1-bad-minor.bin Normal file

Binary file not shown.

View File

@@ -0,0 +1,24 @@
error: Failed to parse TPP1 minor revision number
error: Unknown MBC "TPP1_1.lol"
Accepted MBC names:
ROM ($00) [aka ROM_ONLY]
MBC1 ($02), 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)
HUC3 ($FE)
HUC1+RAM+BATTERY ($FF)
TPP1_1.0, TPP1_1.0+RUMBLE, TPP1_1.0+MULTIRUMBLE, TPP1_1.0+RTC,
TPP1_1.0+RTC+RUMBLE, TPP1_1.0+RTC+MULTIRUMBLE, TPP1_1.0+BATTERY,
TPP1_1.0+BATTERY+RUMBLE, TPP1_1.0+BATTERY+MULTIRUMBLE,
TPP1_1.0+BATTERY+RTC, TPP1_1.0+BATTERY+RTC+RUMBLE,
TPP1_1.0+BATTERY+RTC+MULTIRUMBLE

View File

@@ -0,0 +1 @@
-m TPP1_1.lol

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

Binary file not shown.

5
test/fix/tpp1-nonjap.err Normal file
View File

@@ -0,0 +1,5 @@
warning: TPP1 overwrites region flag for its identification code, ignoring `-j`
warning: Overwrote a non-zero byte in the cartridge type
warning: Overwrote a non-zero byte in the TPP1 identification code
warning: Overwrote a non-zero byte in the TPP1 revision number
warning: Overwrote a non-zero byte in the TPP1 feature flags

View File

@@ -0,0 +1 @@
-m TPP1_1.0 -j

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

Binary file not shown.

BIN
test/fix/tpp1-too-short.bin Normal file

Binary file not shown.

View File

@@ -0,0 +1,2 @@
FATAL: "<filename>" too short, expected at least 340 ($154) bytes, got only 339
Fixing "<filename>" failed with 1 error

View File

@@ -0,0 +1 @@
-m TPP1_1.0

BIN
test/fix/tpp1-unk-major.bin Normal file

Binary file not shown.

View File

@@ -0,0 +1,24 @@
error: RGBFIX only supports TPP1 versions 1.0
error: Unknown MBC "TPP1_2.0"
Accepted MBC names:
ROM ($00) [aka ROM_ONLY]
MBC1 ($02), 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)
HUC3 ($FE)
HUC1+RAM+BATTERY ($FF)
TPP1_1.0, TPP1_1.0+RUMBLE, TPP1_1.0+MULTIRUMBLE, TPP1_1.0+RTC,
TPP1_1.0+RTC+RUMBLE, TPP1_1.0+RTC+MULTIRUMBLE, TPP1_1.0+BATTERY,
TPP1_1.0+BATTERY+RUMBLE, TPP1_1.0+BATTERY+MULTIRUMBLE,
TPP1_1.0+BATTERY+RTC, TPP1_1.0+BATTERY+RTC+RUMBLE,
TPP1_1.0+BATTERY+RTC+MULTIRUMBLE

View File

@@ -0,0 +1 @@
-m TPP1_2.0

View File

@@ -0,0 +1,5 @@
<EFBFBD>!<21>/;t<>c<EFBFBD>k<EFBFBD><6B><EFBFBD><EFBFBD><EFBFBD>n<EFBFBD>;z<><7A><EFBFBD><EFBFBD>gh<67><68>_<05> <0C><><07><> AM<41>JHl<48>a!<21>0w<1D><>B<EFBFBD><42>ub`Aj<41><6A>+<2B><><EFBFBD>jYA b<><62><EFBFBD>#<23><><EFBFBD><EFBFBD>@<40><><07>(<28>#<23><><EFBFBD>P<EFBFBD>g<EFBFBD><06>DOJ<4F><4A><EFBFBD>pz<70>1<EFBFBD><31><EFBFBD><EFBFBD><EFBFBD><04><><EFBFBD><EFBFBD>t<EFBFBD><74>*<2A>
<EFBFBD><EFBFBD><EFBFBD>3<><33><0E><>vQ<76>l<EFBFBD><6C>|W<>v<EFBFBD><76>rx<><02>!-<07>I<EFBFBD>p<EFBFBD>
<EFBFBD>E,@<40><><19><><EFBFBD><EFBFBD>\x;<3B>|k<><6B>(<28><>e<EFBFBD><65><EFBFBD><EFBFBD><EFBFBD>8<EFBFBD>ؤ<02><1E><> 8*<2A><><EFBFBD>R[tf% <09><>yIV}Ɣ<><C694>g<06>/8ӄt<D384><74>2A<>$<24><>̹#<23>E<EFBFBD>XD<58><44>NA0_<30>> ]| <20><11><06><><EFBFBD>:<3A><>)<11>UG<55><EFBFBD><7F>ӿ<EFBFBD><D3BF><EFBFBD>2<EFBFBD>]<5D><><EFBFBD><EFBFBD>"K<><4B>E<><45><EFBFBD><EFBFBD><EFBFBD>C0<43>I<EFBFBD>T<EFBFBD>e<03>[<5B>]<5D>:<3A>$<11>}|<7C>Y<EFBFBD><59>?e<><65><EFBFBD><EFBFBD><EFBFBD>9M<39>tb=$d"<22>#P;<3B>OO<4F>Lu/;.<2E><>4<EFBFBD>o<>qhj9+<2B><18><>%) WM<57>(:<3A>u{<7B>T<EFBFBD>-.8<EFBFBD>& _<><5F><EFBFBD><j(EړY<DA93>zGŢH<C5A2>
<EFBFBD><EFBFBD>;6!<1D>41<34><31><EFBFBD><EFBFBD><EFBFBD><EFBFBD> ?s<><73><EFBFBD><EFBFBD>K4<4B>pj<70>}eW+<2B><><02><14><EFBFBD>P<EFBFBD>w<EFBFBD>2tC۷E<DBB7><45>y,<1F>)<03><>
<EFBFBD><EFBFBD>I%g <09><><EFBFBD><EFBFBD>7Rr

View File

@@ -0,0 +1,24 @@
error: TPP1 minor revision number must be 8-bit
error: Unknown MBC "TPP1_1.256"
Accepted MBC names:
ROM ($00) [aka ROM_ONLY]
MBC1 ($02), 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)
HUC3 ($FE)
HUC1+RAM+BATTERY ($FF)
TPP1_1.0, TPP1_1.0+RUMBLE, TPP1_1.0+MULTIRUMBLE, TPP1_1.0+RTC,
TPP1_1.0+RTC+RUMBLE, TPP1_1.0+RTC+MULTIRUMBLE, TPP1_1.0+BATTERY,
TPP1_1.0+BATTERY+RUMBLE, TPP1_1.0+BATTERY+MULTIRUMBLE,
TPP1_1.0+BATTERY+RTC, TPP1_1.0+BATTERY+RTC+RUMBLE,
TPP1_1.0+BATTERY+RTC+MULTIRUMBLE

View File

@@ -0,0 +1 @@
-m TPP1_1.256