From beeb05420952a3ca106bcc3395ecb9c974b4f464 Mon Sep 17 00:00:00 2001 From: qwx Date: Thu, 10 Feb 2022 00:35:13 +0000 Subject: [PATCH] gba: fix flash chip id for 128k and add setting MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Some gba cartridges use flash chips produced by a few different manufacturers for backup memory. A game rom may then try to read the device id for its flash chip and break if it's the wrong one. There's no way for us to know which chip is supposed to be there, save for looking it up in some database. These chips are either 64k or 128k big. gba(1) hardcodes the id for the SST 64k chip, but games like the Pokémon ones use a 128k Macronix chip and expect a different id, completely breaking them. This patch sets a different default for 128k flash backups, and gives the ability to set the exact type when creating the save file if it's really necessary. This new default fixes the Pokémons. The type is saved in the save file, but this will *not* break existing ones. It may be that we don't need to worry about the type and just have an id that corresponds to the right chip size, which is why these defaults make sense, but I haven't tested more than a dozen roms, mostly since I don't really know which games use 128k flash. --- sys/man/1/nintendo | 4 ++++ sys/src/games/gba/dat.h | 1 + sys/src/games/gba/gba.c | 40 ++++++++++++++++++++++++++++++++++++++-- sys/src/games/gba/mem.c | 4 ++-- 4 files changed, 45 insertions(+), 4 deletions(-) diff --git a/sys/man/1/nintendo b/sys/man/1/nintendo index e0b64d67e..a950245f9 100644 --- a/sys/man/1/nintendo +++ b/sys/man/1/nintendo @@ -112,6 +112,10 @@ Location of the GBA BIOS file (required to operate the emulator). Default is \fB .TP .B -s Save format used by the original game. Valid formats are: eeprom4, eeprom64, sram256, flash512, flash1024. The number corresponds to the size, in kilobits, of the save file. By default, the emulator attempts to automatically detect the save format, but does not always succeed. +Some roms require a specific flash device id which may need to be set manually for them to work. +Valid formats and corresponding ids are: +flash512 (SST), flash512mx (Macronix 64K), flash512pan (Panasonic), flash512atm (Atmel), +flash1024 (Macronix 128K), flash1024san (Sanyo). .PP .B nes options: diff --git a/sys/src/games/gba/dat.h b/sys/src/games/gba/dat.h index d930c7b28..c609926ec 100644 --- a/sys/src/games/gba/dat.h +++ b/sys/src/games/gba/dat.h @@ -9,6 +9,7 @@ extern u16int pram[], oam[]; extern u16int reg[]; extern uchar *rom, *back; extern int nrom, nback, backup; +extern int flashid; extern int hblank, ppuy; diff --git a/sys/src/games/gba/gba.c b/sys/src/games/gba/gba.c index a306c756a..6dbafa315 100644 --- a/sys/src/games/gba/gba.c +++ b/sys/src/games/gba/gba.c @@ -15,6 +15,15 @@ int clock; char *biosfile = "/sys/games/lib/gbabios.bin"; +enum { + IDSST = 0xd4bf, + IDMacronix64 = 0x1cc2, + IDPanasonic = 0x1b32, + IDAtmel = 0x3d1f, + IDSanyo = 0x1362, + IDMacronix128 = 0x09c2, +}; + void writeback(void) { @@ -65,10 +74,12 @@ romtype(int *size) if(v == s3.u){ if(memcmp(p - 1, "FLASH_V", 7) == 0 || memcmp(p - 1, "FLASH512_V", 10) == 0){ *size = 64*KB; + flashid = IDSST; return FLASH; } if(memcmp(p - 1, "FLASH1M_V", 9) == 0){ *size = 128*KB; + flashid = IDMacronix128; return FLASH; } } @@ -90,9 +101,27 @@ parsetype(char *s, int *size) return SRAM; }else if(strcmp(s, "flash512") == 0){ *size = 64*KB; + flashid = IDSST; + return FLASH; + }else if(strcmp(s, "flash512mx") == 0){ + *size = 64*KB; + flashid = IDMacronix64; + return FLASH; + }else if(strcmp(s, "flash512pan") == 0){ + *size = 64*KB; + flashid = IDPanasonic; + return FLASH; + }else if(strcmp(s, "flash512atm") == 0){ + *size = 64*KB; + flashid = IDAtmel; return FLASH; }else if(strcmp(s, "flash1024") == 0){ *size = 128*KB; + flashid = IDMacronix128; + return FLASH; + }else if(strcmp(s, "flash1024san") == 0){ + *size = 128*KB; + flashid = IDSanyo; return FLASH; }else return NOBACK; @@ -101,13 +130,20 @@ parsetype(char *s, int *size) void typename(char *s, int type, int size) { - char *st; + char *st, *id; + id = ""; switch(type){ case EEPROM: st = "eeprom"; break; case FLASH: st = "flash"; + switch(flashid){ + case IDMacronix64: id = "mx"; break; + case IDPanasonic: id = "pan"; break; + case IDAtmel: id = "atm"; break; + case IDSanyo: id = "san"; break; + } break; case SRAM: st = "sram"; @@ -116,7 +152,7 @@ typename(char *s, int type, int size) sysfatal("typestr: unknown type %d -- shouldn't happen", type); return; } - snprint(s, BACKTYPELEN, "%s%d", st, size/128); + snprint(s, BACKTYPELEN, "%s%d%s", st, size/128, id); } void diff --git a/sys/src/games/gba/mem.c b/sys/src/games/gba/mem.c index 500123b4e..4b64f97ab 100644 --- a/sys/src/games/gba/mem.c +++ b/sys/src/games/gba/mem.c @@ -572,7 +572,7 @@ eepromwrite(int n) } } -int flashstate, flashmode, flashbank; +int flashstate, flashmode, flashbank, flashid; enum { FLASHCMD0, @@ -589,7 +589,7 @@ static u8int flashread(u16int a) { if((flashmode & FLASHID) != 0) - return (a & 1) != 0 ? 0xd4 : 0xbf; + return (a & 1) != 0 ? flashid >> 8 : flashid; return back[(flashbank << 16) + a]; }