mirror of
https://github.com/lesserkuma/FlashGBX.git
synced 2026-03-21 17:44:30 -05:00
3.7
This commit is contained in:
parent
b4d6a40077
commit
0deedd5956
29
CHANGES.md
29
CHANGES.md
|
|
@ -1,4 +1,19 @@
|
|||
# Release notes
|
||||
### v3.7 (released 2022-03-30)
|
||||
- Updated the Game Boy Advance lookup database for save types, ROM sizes and checksums (improves support for Classic NES Series, NES Classics and Famicom Mini cartridges)
|
||||
- When writing new ROMs to Nintendo Power GB Memory Cartridges (DMG-MMSA-JPN), hidden sector data will now be auto-generated if it’s not provided by the user in form of a .map file
|
||||
- Erasing save data of Game Boy Advance cartridges with the 512K FLASH and 1M FLASH save types is now faster
|
||||
- Windows Setup Package: Updated the CH340/CH341 driver to the latest version (01/18/2022, 3.7.2022.01)
|
||||
- Fixed a bug introduced in v3.4 that broke writing ROMs to SD008-6810-V5 with MX29CL256FH cartridges
|
||||
- Added support for AGB-E05-01 with S29GL064 *(thanks DevDavisNunez)*
|
||||
- Added support for DIY carts with MBC1 and AM29F010 @ AUDIO *(thanks JS7457)*
|
||||
- Added support for DIY carts with MBC1 and AM29F040 @ AUDIO *(thanks JS7457)*
|
||||
- Added support for DIY carts with MBC1 and AM29F080 @ AUDIO *(thanks Timville)*
|
||||
- Added support for DIY carts with MBC1 and AT49F040 @ AUDIO *(thanks Timville)*
|
||||
- Added support for DIY carts with MBC1 and SST39SF040 @ AUDIO *(thanks Timville)*
|
||||
- Added support for B100 with MX29LV640ET *(thanks Mr_V)*
|
||||
- Added support for B54 with MX29LV320ET *(thanks Mr_V)*
|
||||
|
||||
### v3.6 (released 2022-03-09)
|
||||
- When opening Game Boy Camera Album Viewer manually, the save data will now automatically be loaded if a Game Boy Camera or Pocket Camera cartridge is connected
|
||||
- Fixed a bug with the insideGadgets 4 MB (S29GL032M) cartridge *(thanks frarees)*
|
||||
|
|
@ -6,7 +21,7 @@
|
|||
- Added support for Flash Advance Card 64M with 28F640J3A120 *(thanks manuelcm1)*
|
||||
- Fixed a bug with writing ROMs to insideGadgets rumble cartridges on the GBxCart RW v1.3 hardware running the L1 firmware *(thanks DevDavisNunez)*
|
||||
- In GUI mode, flashable cartridges can now completely be wiped of their ROM data by not selecting any file when using the Write ROM feature *(thanks daidianren for the suggestion)*
|
||||
- Fixed a bug introduced in v3.4 with making a ROM backup of Nintendo Power GB Memory cartridges
|
||||
- Fixed a bug introduced in v3.4 with making a ROM backup of Nintendo Power GB Memory Cartridges (DMG-MMSA-JPN)
|
||||
- Bundles GBxCart RW v1.4 firmware version R34+L5 (enables support for some more flash cartridges)
|
||||
- Added support for DIY cartridges with the AT49F040 flash chip for up to 512 KB of ROM data (requires at least GBxCart RW revision v1.4 and firmware version R34+L5) *(thanks Timville)*
|
||||
- Added support for the insideGadgets 512 KB flash cartridge (requires at least GBxCart RW revision v1.4 and firmware version R34+L5) *(thanks Timville and marv17)*
|
||||
|
|
@ -38,7 +53,7 @@
|
|||
- Extracted Game Boy Camera pictures can now have a frame around them; this frame can be customized by placing a file called `pc_frame.png` (must be at least 160×144 pixels) into the configuration directory
|
||||
|
||||
### v3.2 (released 2021-12-18)
|
||||
- Fixed the configuration files for DIY cart with AM29F016/AM29F016B *(thanks dyf2007)*
|
||||
- Fixed the configuration files for DIY carts with AM29F016/AM29F016B *(thanks dyf2007)*
|
||||
- Added support for SD008-6810-V5 with MX29CL256FH (multigame cartridge with 32 MB of ROM and 512 KB of save data)
|
||||
- Added support for SD008-6810-V4 with MX29GL256EL *(thanks LucentW)*
|
||||
- Added support for the [HDR Game Boy Camera Flashcart](https://github.com/HDR/Gameboy-Camera-Flashcart) (select manually if auto-detected option doesn’t work)
|
||||
|
|
@ -104,7 +119,7 @@
|
|||
|
||||
### v2.3 (released 2021-06-08)
|
||||
- Added support for AGB-E05-06L with 29LV128DBT2C-90Q *(thanks marv17)*
|
||||
- Nintendo Power GB Memory Cartridges will now be unlocked properly even if they’re stuck in erase mode *(thanks Grender for testing)*
|
||||
- Nintendo Power GB Memory Cartridges (DMG-MMSA-JPN) will now be unlocked properly even if they’re stuck in erase mode *(thanks Grender for testing)*
|
||||
- Confirmed support for SD007_TSOP_48BALL_V10 with GL032M10BFIR3 *(thanks Mr_V)*
|
||||
- Added support for 2006_TSOP_64BALL_6106 with W29GL128SH9B *(thanks marv17)*
|
||||
- Fixed support for insideGadgets 1 MB, 128 KB SRAM *(thanks AlexiG)*
|
||||
|
|
@ -124,11 +139,11 @@
|
|||
- Added support for SD007_TSOP_48BALL_V10 with M29W320DT *(thanks Jayro)*
|
||||
- Fixed a problem of reading from a certain type of cartridge that uses the GL256S flash chip *(thanks marv17)*
|
||||
- Added support for B11 with 26L6420MC-90 *(thanks dyf2007)*
|
||||
- Added support for a DIY cart with MBC3 and MX29LV640 *(thanks eveningmoose)*
|
||||
- Added support for DIY carts with MBC3 and MX29LV640 *(thanks eveningmoose)*
|
||||
|
||||
### v2.1 (released 2021-05-05)
|
||||
- Fixed support for SD007_TSOP_29LV017D with L017D70VC *(thanks marv17 and 90sFlav)*
|
||||
- Added support for a DIY cart with MBC1 and AM29F080 *(thanks skite2001)*
|
||||
- Added support for DIY carts with MBC1 and AM29F080 *(thanks skite2001)*
|
||||
- Added support for SD007_TSOP_48BALL_V8 with 29LV320CTTC *(thanks Jayro)*
|
||||
- Added the MBC5+SRAM mapper type which is officially unused, but is actually used by GB Studio *(thanks Jayro)*
|
||||
- The GBxCart RW v1.3 firmware updater should now also work if the device is below firmware version R19
|
||||
|
|
@ -170,7 +185,7 @@
|
|||
- Fixed minor bugs
|
||||
|
||||
### v1.4.1 (released 2021-03-15)
|
||||
- Added ROM and map backup support for official Nintendo Power GB Memory cartridges (DMG-MMSA-JPN); save data handling and ROM writing is not supported yet
|
||||
- Added ROM and map backup support for official Nintendo Power GB Memory Cartridges (DMG-MMSA-JPN); save data handling and ROM writing is not supported yet
|
||||
- Added preliminary support for 4050M0Y0Q0-39VF512 with 4050M0Y0Q0 (requires a future firmware update of GBxCart RW)
|
||||
- Added preliminary support for official cartridges with the MBC7 memory bank controller; tested with “Korokoro Kirby” (CGB-KKKJ-JPN) (requires a future firmware update of GBxCart RW)
|
||||
- Added support for official cartridges with the M161 memory bank controller; tested with “Mani 4 in 1: Tetris + Alleyway + Yakuman + Tennis” (DMG-601CHN) (requires GBxCart RW firmware R26 or newer)
|
||||
|
|
@ -276,7 +291,7 @@
|
|||
- Renamed config.ini to settings.ini to avoid confusion with the term “config file”
|
||||
|
||||
### v0.8β (released 2020-10-03)
|
||||
- Added support for the DIY cart with AM29F016/AM29F016B with AUDIO as WE *(thanks AndehX)*
|
||||
- Added support for DIY carts with AM29F016/AM29F016B with AUDIO as WE *(thanks AndehX)*
|
||||
- Renamed `VIN` to `AUDIO` in config files and the command line switch `--resetconfig` to `--reset`
|
||||
- Added experimental support for GBxCart RW revisions other than v1.3 and fixed a crash when connecting to unknown revisions of the GBxCart RW
|
||||
- The app is now available as a package and can be installed directly through *pip* *(thanks JFox)*
|
||||
|
|
|
|||
|
|
@ -128,7 +128,7 @@ def main(portableMode=False):
|
|||
ap_cli2.add_argument("--dmg-mbc", choices=["auto", "1", "2", "3", "5", "6", "7"], type=str.lower, default="auto", help="set memory bank controller type of Game Boy cartridge")
|
||||
ap_cli2.add_argument("--dmg-savesize", choices=["auto", "4k", "16k", "64k", "256k", "512k", "1m", "eeprom2k", "eeprom4k", "tama5", "4m"], type=str.lower, default="auto", help="set size of Game Boy cartridge save data")
|
||||
ap_cli2.add_argument("--agb-romsize", choices=["auto", "4mb", "8mb", "16mb", "32mb", "64mb", "128mb", "256mb"], type=str.lower, default="auto", help="set size of Game Boy Advance cartridge ROM data")
|
||||
ap_cli2.add_argument("--agb-savetype", choices=["auto", "eeprom4k", "eeprom64k", "sram256k", "sram512k", "sram1m", "flash512k", "flash1m", "dacs8m"], type=str.lower, default="auto", help="set type of Game Boy cartridge save data")
|
||||
ap_cli2.add_argument("--agb-savetype", choices=["auto", "eeprom4k", "eeprom64k", "sram256k", "flash512k", "flash1m", "dacs8m", "sram512k", "sram1m"], type=str.lower, default="auto", help="set type of Game Boy Advance cartridge save data")
|
||||
ap_cli2.add_argument("--store-rtc", action="store_true", help="store RTC register values if supported")
|
||||
ap_cli2.add_argument("--ignore-bad-header", action="store_true", help="don’t stop if invalid data found in cartridge header data")
|
||||
#ap_cli2.add_argument("--fast-read-mode", action="store_true", help="enable experimental fast read mode for GBxCart RW v1.3")
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ class FlashGBX_CLI():
|
|||
dev = self.DEVICE[1]
|
||||
builddate = dev.GetFWBuildDate()
|
||||
if builddate != "":
|
||||
print("\nConnected to {:s} (dated {:s})".format(dev.GetFullNameExtended(), builddate))
|
||||
print("\nConnected to {:s}".format(dev.GetFullNameExtended(more=True)))
|
||||
else:
|
||||
print("\nConnected to {:s}".format(dev.GetFullNameExtended()))
|
||||
|
||||
|
|
@ -482,7 +482,7 @@ class FlashGBX_CLI():
|
|||
|
||||
if data['logo_correct'] and not self.CONN.IsSupportedMbc(data["features_raw"]):
|
||||
print("{:s}\nWARNING: This cartridge uses a mapper that may not be completely supported by {:s} using the current firmware version of the {:s} device. Please check for firmware updates.{:s}".format(ANSI.YELLOW, APPNAME, self.CONN.GetFullName(), ANSI.RESET))
|
||||
if data['logo_correct'] and data['game_title'] == "NP M-MENU MENU" and self.ARGS["argparsed"].flashcart_type == "autodetect":
|
||||
if data['logo_correct'] and data['game_title'] in ("NP M-MENU MENU", "DMG MULTI MENU ") and self.ARGS["argparsed"].flashcart_type == "autodetect":
|
||||
cart_types = self.CONN.GetSupportedCartridgesDMG()
|
||||
for i in range(0, len(cart_types[0])):
|
||||
if "DMG-MMSA-JPN" in cart_types[0][i]:
|
||||
|
|
@ -577,8 +577,8 @@ class FlashGBX_CLI():
|
|||
data["save_type"] = db_agb_entry['st']
|
||||
if data["dacs_8m"] is True:
|
||||
stok = True
|
||||
s += "Save Type: {:s}\n".format(Util.AGB_Header_Save_Types[8])
|
||||
data["save_type"] = 8
|
||||
s += "Save Type: {:s}\n".format(Util.AGB_Header_Save_Types[6])
|
||||
data["save_type"] = 6
|
||||
|
||||
if stok is False:
|
||||
s += "Save Type: Not detected\n"
|
||||
|
|
@ -620,7 +620,6 @@ class FlashGBX_CLI():
|
|||
|
||||
if len(cart_types) > 0:
|
||||
cart_type = cart_type_id
|
||||
#self.STATUS["cart_type"] = supp_cart_types[1][cart_type]
|
||||
for i in range(0, len(cart_types)):
|
||||
if cart_types[i] == cart_type_id:
|
||||
msg_cart_type += "- {:s}*\n".format(supp_cart_types[0][cart_types[i]])
|
||||
|
|
@ -671,6 +670,8 @@ class FlashGBX_CLI():
|
|||
elif ("[WR / AAA/A9]" in flash_id): msg_cart_type_s += " For ROM writing, you can give the option called “Generic Flash Cartridge (WR/AAA/A9)” a try."
|
||||
elif ("[WR / 555/AA]" in flash_id): msg_cart_type_s += " For ROM writing, you can give the option called “Generic Flash Cartridge (WR/555/AA)” a try."
|
||||
elif ("[WR / 555/A9]" in flash_id): msg_cart_type_s += " For ROM writing, you can give the option called “Generic Flash Cartridge (WR/555/A9)” a try."
|
||||
elif ("[AUDIO/ AAA/AA]" in flash_id): msg_cart_type_s += " For ROM writing, you can give the option called “Generic Flash Cartridge (AUDIO/AAA/AA)” a try."
|
||||
elif ("[AUDIO/ 555/AA]" in flash_id): msg_cart_type_s += " For ROM writing, you can give the option called “Generic Flash Cartridge (AUDIO/555/AA)” a try."
|
||||
msg_cart_type_s += "\n"
|
||||
else:
|
||||
msg_cart_type_s = "Cartridge Type: Generic ROM Cartridge (not rewritable or not auto-detectable)\n"
|
||||
|
|
@ -691,7 +692,6 @@ class FlashGBX_CLI():
|
|||
def BackupROM(self, args, header):
|
||||
mbc = 1
|
||||
rom_size = 0
|
||||
#fast_read_mode = args.fast_read_mode is True
|
||||
|
||||
if self.CONN.GetMode() == "DMG":
|
||||
if args.dmg_mbc == "auto":
|
||||
|
|
@ -711,11 +711,9 @@ class FlashGBX_CLI():
|
|||
|
||||
if args.dmg_romsize == "auto":
|
||||
try:
|
||||
#rom_banks = Util.DMG_Header_ROM_Sizes_Flasher_Map[header["rom_size_raw"]]
|
||||
rom_size = Util.DMG_Header_ROM_Sizes_Flasher_Map[header["rom_size_raw"]]
|
||||
except:
|
||||
print("{:s}Couldn’t determine ROM size, will use 8 MB. It can also be manually set with the “--dmg-romsize” command line switch.{:s}".format(ANSI.YELLOW, ANSI.RESET))
|
||||
#rom_banks = 512
|
||||
rom_size = 8 * 1024 * 1024
|
||||
else:
|
||||
sizes = [ "auto", "32kb", "64kb", "128kb", "256kb", "512kb", "1mb", "2mb", "4mb", "8mb", "16mb", "32mb" ]
|
||||
|
|
@ -766,9 +764,12 @@ class FlashGBX_CLI():
|
|||
print("{:s}Couldn’t access “{:s}”.{:s}".format(ANSI.RED, path, ANSI.RESET))
|
||||
return
|
||||
|
||||
#if fast_read_mode: print("Fast Read Mode enabled.")
|
||||
s_mbc = ""
|
||||
if self.CONN.GetMode() == "DMG": s_mbc = " using Mapper Type 0x{:X}".format(mbc)
|
||||
if self.CONN.GetMode() == "DMG":
|
||||
if mbc in Util.DMG_Header_Mapper:
|
||||
s_mbc = " using Mapper Type “{:s}”".format(Util.DMG_Header_Mapper[mbc])
|
||||
else:
|
||||
s_mbc = " using Mapper Type 0x{:X}".format(mbc)
|
||||
if self.CONN.GetMode() == "DMG":
|
||||
print("The ROM will now be read{:s} and saved to “{:s}”.".format(s_mbc, os.path.abspath(path)))
|
||||
else:
|
||||
|
|
@ -788,7 +789,6 @@ class FlashGBX_CLI():
|
|||
if carts[i]["type"] != self.CONN.GetMode(): continue
|
||||
if args.flashcart_type in carts[i]["names"]:
|
||||
print("Selected flash cartridge type: {:s}".format(args.flashcart_type))
|
||||
#rom_banks = int(carts[i]["flash_size"] / 0x4000)
|
||||
rom_size = carts[i]["flash_size"]
|
||||
cart_type = i
|
||||
break
|
||||
|
|
@ -815,7 +815,6 @@ class FlashGBX_CLI():
|
|||
break
|
||||
|
||||
if cart_type <= 0 and args.flashcart_type == "autodetect":
|
||||
#cart_type = self.DetectCartridge(limitVoltage=not args.force_5v)
|
||||
cart_type = self.DetectCartridge()
|
||||
if cart_type is None: cart_type = 0
|
||||
if cart_type == 0:
|
||||
|
|
@ -875,7 +874,6 @@ class FlashGBX_CLI():
|
|||
if not prefer_chip_erase and 'chip_erase' in carts[cart_type]['commands'] and 'sector_erase' in carts[cart_type]['commands']:
|
||||
print("This flash cartridge supports both Sector Erase and Full Chip Erase methods. You can use the “--prefer-chip-erase” command line switch if necessary.")
|
||||
|
||||
#fast_read_mode = args.fast_read_mode is True
|
||||
verify_write = args.no_verify_write is False
|
||||
|
||||
fix_header = False
|
||||
|
|
@ -898,7 +896,6 @@ class FlashGBX_CLI():
|
|||
return
|
||||
|
||||
print("")
|
||||
#if fast_read_mode: print("Fast Read Mode enabled for flash verification.")
|
||||
v = carts[cart_type]["voltage"]
|
||||
if override_voltage: v = override_voltage
|
||||
print("The following ROM file will now be written to the flash cartridge at {:s}V:\n{:s}".format(str(v), os.path.abspath(path)))
|
||||
|
|
@ -958,7 +955,7 @@ class FlashGBX_CLI():
|
|||
if args.agb_savetype == "auto":
|
||||
save_type = header["save_type"]
|
||||
else:
|
||||
sizes = [ "auto", "eeprom4k", "eeprom64k", "sram256k", "sram512k", "sram1m", "flash512k", "flash1m", "dacs8m" ]
|
||||
sizes = [ "auto", "eeprom4k", "eeprom64k", "sram256k", "flash512k", "flash1m", "dacs8m", "sram512k", "sram1m" ]
|
||||
save_type = sizes.index(args.agb_savetype)
|
||||
|
||||
path = header["game_title"].strip().encode('ascii', 'ignore').decode('ascii')
|
||||
|
|
@ -987,7 +984,11 @@ class FlashGBX_CLI():
|
|||
if (path == ""): return
|
||||
|
||||
s_mbc = ""
|
||||
if self.CONN.GetMode() == "DMG": s_mbc = " using Mapper Type 0x{:X}".format(mbc)
|
||||
if self.CONN.GetMode() == "DMG":
|
||||
if mbc in Util.DMG_Header_Mapper:
|
||||
s_mbc = " using Mapper Type “{:s}”".format(Util.DMG_Header_Mapper[mbc])
|
||||
else:
|
||||
s_mbc = " using Mapper Type 0x{:X}".format(mbc)
|
||||
if args.action == "backup-save":
|
||||
if not args.overwrite and os.path.exists(os.path.abspath(path)):
|
||||
answer = input("The target file “{:s}” already exists.\nDo you want to overwrite it? [y/N]: ".format(os.path.abspath(path))).strip().lower()
|
||||
|
|
@ -1040,8 +1041,6 @@ class FlashGBX_CLI():
|
|||
self.CONN.TransferData(args={ 'mode':3, 'path':path, 'mbc':mbc, 'save_type':save_type, 'erase':True, 'rtc':rtc }, signal=self.PROGRESS.SetProgress)
|
||||
elif args.action == "debug-test-save": # debug
|
||||
self.ARGS["debug"] = True
|
||||
#self.CONN.DetectCartridge()
|
||||
#return
|
||||
|
||||
print("Making a backup of the original save data.")
|
||||
ret = self.CONN.TransferData(args={ 'mode':2, 'path':self.CONFIG_PATH + "/test1.bin", 'mbc':mbc, 'save_type':save_type }, signal=self.PROGRESS.SetProgress)
|
||||
|
|
@ -1056,10 +1055,12 @@ class FlashGBX_CLI():
|
|||
self.CONN.TransferData(args={ 'mode':2, 'path':self.CONFIG_PATH + "/test3.bin", 'mbc':mbc, 'save_type':save_type }, signal=self.PROGRESS.SetProgress)
|
||||
time.sleep(0.1)
|
||||
with open(self.CONFIG_PATH + "/test3.bin", "rb") as f: test3 = bytearray(f.read())
|
||||
print("\nPower cycling.")
|
||||
self.CONN.CartPowerOff()
|
||||
time.sleep(1)
|
||||
self.CONN.CartPowerOn()
|
||||
if self.CONN.CanPowerCycleCart():
|
||||
print("\nPower cycling.")
|
||||
self.CONN.CartPowerOff()
|
||||
time.sleep(1)
|
||||
self.CONN.CartPowerOn()
|
||||
self.CONN.ReadInfo(checkRtc=False)
|
||||
time.sleep(0.2)
|
||||
print("\nReading back and comparing data again.")
|
||||
self.CONN.TransferData(args={ 'mode':2, 'path':self.CONFIG_PATH + "/test4.bin", 'mbc':mbc, 'save_type':save_type }, signal=self.PROGRESS.SetProgress)
|
||||
|
|
@ -1069,6 +1070,11 @@ class FlashGBX_CLI():
|
|||
self.CONN.TransferData(args={ 'mode':3, 'path':self.CONFIG_PATH + "/test1.bin", 'mbc':mbc, 'save_type':save_type, 'erase':False }, signal=self.PROGRESS.SetProgress)
|
||||
time.sleep(0.1)
|
||||
|
||||
if mbc == 6:
|
||||
for i in range(0, len(test2)):
|
||||
test2[i] &= 0x0F
|
||||
test3[i] &= 0x0F
|
||||
|
||||
if test2 != test4:
|
||||
diffcount = 0
|
||||
for i in range(0, len(test2)):
|
||||
|
|
@ -1080,11 +1086,6 @@ class FlashGBX_CLI():
|
|||
if test3[i] != test4[i]: diffcount += 1
|
||||
print("\n{:s}Differences found between two consecutive readbacks: {:d}{:s}".format(ANSI.RED, diffcount, ANSI.RESET))
|
||||
|
||||
if mbc == 6:
|
||||
for i in range(0, len(test2)):
|
||||
test2[i] &= 0x0F
|
||||
test3[i] &= 0x0F
|
||||
|
||||
found_offset = test2.find(test3[0:512])
|
||||
if found_offset < 0:
|
||||
if self.CONN.GetMode() == "AGB":
|
||||
|
|
@ -1150,9 +1151,8 @@ class FlashGBX_CLI():
|
|||
self.INI = Util.IniSettings(ini=ini_file, main_section="Firmware")
|
||||
fw_ver = self.INI.GetValue("fw_ver")
|
||||
fw_buildts = self.INI.GetValue("fw_buildts")
|
||||
#fw_text = self.INI.GetValue("fw_text")
|
||||
|
||||
print("Available firmware version:\n{:s}\n".format("{:s} (dated {:s})".format(fw_ver, datetime.datetime.fromtimestamp(int(fw_buildts)).astimezone().replace(microsecond=0).isoformat())))
|
||||
print("Available firmware version:\n{:s}\n".format("{:s} ({:s})".format(fw_ver, datetime.datetime.fromtimestamp(int(fw_buildts)).astimezone().replace(microsecond=0).isoformat())))
|
||||
print("Please follow these steps to proceed with the firmware update:\n1. Disconnect the USB cable of your GBxCart RW {:s} device.\n2. On the circuit board of your GBxCart RW {:s}, press and hold down\n the small button while connecting the USB cable again.\n3. Keep the small button held for at least 2 seconds, then let go of it.\n If done right, the green LED labeled “Done” should remain lit.\n4. Press ENTER or RETURN to continue.".format(device_name, device_name))
|
||||
if len(input("").strip()) != 0:
|
||||
print("Canceled.")
|
||||
|
|
|
|||
|
|
@ -189,14 +189,11 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
if platform.system() == "Darwin": btnWidth += 12
|
||||
self.btnConfig.setMaximumWidth(btnWidth)
|
||||
|
||||
#self.mnuDevice = QtWidgets.QMenu("&Device options")
|
||||
|
||||
self.mnuConfig = QtWidgets.QMenu()
|
||||
self.mnuConfig.addAction("Check for &updates at application startup", lambda: [ self.SETTINGS.setValue("UpdateCheck", str(self.mnuConfig.actions()[0].isChecked()).lower().replace("true", "enabled").replace("false", "disabled")), self.UpdateCheck() ])
|
||||
self.mnuConfig.addAction("&Append date && time to filename of save data backups", lambda: self.SETTINGS.setValue("SaveFileNameAddDateTime", str(self.mnuConfig.actions()[1].isChecked()).lower().replace("true", "enabled").replace("false", "disabled")))
|
||||
self.mnuConfig.addAction("Prefer full &chip erase over sector erase when both available", lambda: self.SETTINGS.setValue("PreferChipErase", str(self.mnuConfig.actions()[2].isChecked()).lower().replace("true", "enabled").replace("false", "disabled")))
|
||||
self.mnuConfig.addAction("&Verify data after writing", lambda: self.SETTINGS.setValue("VerifyWrittenData", str(self.mnuConfig.actions()[3].isChecked()).lower().replace("true", "enabled").replace("false", "disabled")))
|
||||
#self.mnuConfig.addAction("Use &fast read mode", lambda: self.SETTINGS.setValue("FastReadMode", str(self.mnuConfig.actions()[4].isChecked()).lower().replace("true", "enabled").replace("false", "disabled"))) # GBxCart RW
|
||||
self.mnuConfig.addAction("&Limit voltage to 3.3V when detecting Game Boy flash cartridges", lambda: self.SETTINGS.setValue("AutoDetectLimitVoltage", str(self.mnuConfig.actions()[4].isChecked()).lower().replace("true", "enabled").replace("false", "disabled")))
|
||||
self.mnuConfig.addSeparator()
|
||||
self.mnuConfig.addAction("Re-&enable suppressed messages", self.ReEnableMessages)
|
||||
|
|
@ -206,13 +203,11 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
self.mnuConfig.actions()[1].setCheckable(True)
|
||||
self.mnuConfig.actions()[2].setCheckable(True)
|
||||
self.mnuConfig.actions()[3].setCheckable(True)
|
||||
#self.mnuConfig.actions()[4].setCheckable(True) # GBxCart RW
|
||||
self.mnuConfig.actions()[4].setCheckable(True)
|
||||
self.mnuConfig.actions()[0].setChecked(self.SETTINGS.value("UpdateCheck") == "enabled")
|
||||
self.mnuConfig.actions()[1].setChecked(self.SETTINGS.value("SaveFileNameAddDateTime", default="disabled") == "enabled")
|
||||
self.mnuConfig.actions()[2].setChecked(self.SETTINGS.value("PreferChipErase", default="disabled") == "enabled")
|
||||
self.mnuConfig.actions()[3].setChecked(self.SETTINGS.value("VerifyWrittenData", default="enabled") == "enabled")
|
||||
#self.mnuConfig.actions()[4].setChecked(self.SETTINGS.value("FastReadMode", default="disabled") == "enabled") # GBxCart RW
|
||||
self.mnuConfig.actions()[4].setChecked(self.SETTINGS.value("AutoDetectLimitVoltage", default="disabled") == "enabled")
|
||||
|
||||
self.btnConfig.setMenu(self.mnuConfig)
|
||||
|
|
@ -280,14 +275,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
rowHeaderRevision.addWidget(self.lblHeaderRevisionResult)
|
||||
group_layout.addLayout(rowHeaderRevision)
|
||||
|
||||
#rowHeaderGB = QtWidgets.QHBoxLayout()
|
||||
#lblHeaderGB = QtWidgets.QLabel("Target Platform:")
|
||||
#lblHeaderGB.setContentsMargins(0, 1, 0, 1)
|
||||
#rowHeaderGB.addWidget(lblHeaderGB)
|
||||
#self.lblHeaderGBResult = QtWidgets.QLabel("")
|
||||
#rowHeaderGB.addWidget(self.lblHeaderGBResult)
|
||||
#group_layout.addLayout(rowHeaderGB)
|
||||
|
||||
rowHeaderRtc = QtWidgets.QHBoxLayout()
|
||||
lblHeaderRtc = QtWidgets.QLabel("Real Time Clock:")
|
||||
lblHeaderRtc.setContentsMargins(0, 1, 0, 1)
|
||||
|
|
@ -393,14 +380,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
rowAGBHeaderRevision.addWidget(self.lblAGBHeaderRevisionResult)
|
||||
group_layout.addLayout(rowAGBHeaderRevision)
|
||||
|
||||
#rowAGBHeader96h = QtWidgets.QHBoxLayout()
|
||||
#lblAGBHeader96h = QtWidgets.QLabel("Cartridge Identifier:")
|
||||
#lblAGBHeader96h.setContentsMargins(0, 1, 0, 1)
|
||||
#rowAGBHeader96h.addWidget(lblAGBHeader96h)
|
||||
self.lblAGBHeader96hResult = QtWidgets.QLabel("")
|
||||
#rowAGBHeader96h.addWidget(self.lblAGBHeader96hResult)
|
||||
#group_layout.addLayout(rowAGBHeader96h)
|
||||
|
||||
rowAGBGpioRtc = QtWidgets.QHBoxLayout()
|
||||
lblAGBGpioRtc = QtWidgets.QLabel("Real Time Clock:")
|
||||
lblAGBGpioRtc.setContentsMargins(0, 1, 0, 1)
|
||||
|
|
@ -557,7 +536,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
self.btnRestoreRAM.setEnabled(False)
|
||||
self.btnConnect.setText("&Connect")
|
||||
self.lblDevice.setText("Disconnected.")
|
||||
#self.mnuTools.actions()[2].setEnabled(False)
|
||||
|
||||
def ReEnableMessages(self):
|
||||
self.SETTINGS.setValue("AutoReconnect", "disabled")
|
||||
|
|
@ -756,13 +734,14 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
self.btnConnect.setEnabled(True)
|
||||
|
||||
if len(self.DEVICES) == 0: return False
|
||||
|
||||
return True
|
||||
|
||||
def AbortOperation(self):
|
||||
self.CONN.CANCEL = True
|
||||
self.CONN.ERROR = False
|
||||
|
||||
self.lblStatus4a.setText("Stopping... Please wait.")
|
||||
self.lblStatus4aResult.setText("")
|
||||
|
||||
def FinishOperation(self):
|
||||
if self.lblStatus2aResult.text() == "Pending...": self.lblStatus2aResult.setText("–")
|
||||
self.lblStatus4aResult.setText("")
|
||||
|
|
@ -1013,9 +992,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
|
||||
def FlashROM(self, dpath=""):
|
||||
if not self.CheckDeviceAlive(): return
|
||||
#if "cart_type" in self.STATUS and "dmg-mmsa-jpn" in self.STATUS["cart_type"]:
|
||||
# self.ShowGBMemoryWindow()
|
||||
# return
|
||||
|
||||
just_erase = False
|
||||
path = ""
|
||||
|
|
@ -1081,11 +1057,11 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
msg += " You can still give it a try, but it’s possible that it’s too large which may cause the ROM writing to fail."
|
||||
answer = QtWidgets.QMessageBox.warning(self, "{:s} {:s}".format(APPNAME, VERSION), msg, QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel, QtWidgets.QMessageBox.Cancel)
|
||||
if answer == QtWidgets.QMessageBox.Cancel: return
|
||||
|
||||
|
||||
override_voltage = False
|
||||
if 'voltage_variants' in carts[cart_type] and carts[cart_type]['voltage'] == 3.3:
|
||||
msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Question, windowTitle="{:s} {:s}".format(APPNAME, VERSION), text="The selected flash cartridge type usually flashes fine with 3.3V, however sometimes it may require 5V. Which mode should be used?")
|
||||
button_3_3v = msgbox.addButton(" Use &3.3V (safer) ", QtWidgets.QMessageBox.ActionRole)
|
||||
msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Question, windowTitle="{:s} {:s}".format(APPNAME, VERSION), text="Some cartridges of this type can be flashed at 3.3V, others may require 5V. Which mode should be used?")
|
||||
button_3_3v = msgbox.addButton("Use &3.3V", QtWidgets.QMessageBox.ActionRole)
|
||||
button_5v = msgbox.addButton("Use &5V", QtWidgets.QMessageBox.ActionRole)
|
||||
button_cancel = msgbox.addButton("&Cancel", QtWidgets.QMessageBox.RejectRole)
|
||||
msgbox.setDefaultButton(button_3_3v)
|
||||
|
|
@ -1114,12 +1090,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
else:
|
||||
prefer_chip_erase = False
|
||||
|
||||
#fast_read_mode = self.SETTINGS.value("FastReadMode", default="disabled")
|
||||
#if fast_read_mode and fast_read_mode.lower() == "enabled":
|
||||
# fast_read_mode = True
|
||||
#else:
|
||||
# fast_read_mode = False
|
||||
|
||||
verify_write = self.SETTINGS.value("VerifyWrittenData", default="enabled")
|
||||
if verify_write and verify_write.lower() == "enabled":
|
||||
verify_write = True
|
||||
|
|
@ -1439,7 +1409,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
self.btnRestoreRAM.setEnabled(True)
|
||||
self.btnHeaderRefresh.setFocus()
|
||||
self.SetProgressBars(min=0, max=100, value=0)
|
||||
#if "has_rtc" in data and data["has_rtc"] is True: print("Real Time Clock cartridge detected.")
|
||||
self.lblStatus4a.setText("Ready.")
|
||||
qt_app.processEvents()
|
||||
|
||||
|
|
@ -1556,7 +1525,7 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
self.lblHeaderTitleResult.setStyleSheet(self.lblHeaderRevisionResult.styleSheet())
|
||||
if data['logo_correct'] and not self.CONN.IsSupportedMbc(data["features_raw"]) and resetStatus:
|
||||
QtWidgets.QMessageBox.warning(self, "{:s} {:s}".format(APPNAME, VERSION), "This cartridge uses a mapper that may not be completely supported by {:s} using the current firmware version of the {:s} device. Please check for firmware updates in the Tools menu or the maker’s website.".format(APPNAME, self.CONN.GetFullName()), QtWidgets.QMessageBox.Ok)
|
||||
if data['logo_correct'] and data['game_title'] == "NP M-MENU MENU":
|
||||
if data['logo_correct'] and data['game_title'] in ("NP M-MENU MENU", "DMG MULTI MENU "):
|
||||
cart_types = self.CONN.GetSupportedCartridgesDMG()
|
||||
for i in range(0, len(cart_types[0])):
|
||||
if "dmg-mmsa-jpn" in cart_types[1][i]:
|
||||
|
|
@ -1582,13 +1551,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
self.lblAGBHeaderLogoValidResult.setText("Invalid")
|
||||
self.lblAGBHeaderLogoValidResult.setStyleSheet("QLabel { color: red; }")
|
||||
|
||||
if data['96h_correct']:
|
||||
self.lblAGBHeader96hResult.setText("OK")
|
||||
self.lblAGBHeader96hResult.setStyleSheet(self.lblAGBHeaderCodeResult.styleSheet())
|
||||
else:
|
||||
self.lblAGBHeader96hResult.setText("Invalid")
|
||||
self.lblAGBHeader96hResult.setStyleSheet("QLabel { color: red; }")
|
||||
|
||||
if data['has_rtc']:
|
||||
if 'rtc_buffer' in data:
|
||||
try:
|
||||
|
|
@ -1657,7 +1619,7 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
if db_agb_entry['st'] < len(Util.AGB_Header_Save_Types):
|
||||
self.cmbAGBSaveTypeResult.setCurrentIndex(db_agb_entry['st'])
|
||||
if data["dacs_8m"] is True:
|
||||
self.cmbAGBSaveTypeResult.setCurrentIndex(8)
|
||||
self.cmbAGBSaveTypeResult.setCurrentIndex(6)
|
||||
|
||||
if data['empty'] == True: # defaults
|
||||
if data['empty_nocart'] == True:
|
||||
|
|
@ -1704,7 +1666,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
self.lblStatus4a.setText("Detecting Cartridge...")
|
||||
self.SetProgressBars(min=0, max=0, value=1)
|
||||
qt_app.processEvents()
|
||||
#self.ReadCartridge(resetStatus=False)
|
||||
|
||||
limitVoltage = str(self.SETTINGS.value("AutoDetectLimitVoltage", default="disabled")).lower() == "enabled"
|
||||
ret = self.CONN.DetectCartridge(limitVoltage=limitVoltage, checkSaveType=not canSkipMessage)
|
||||
|
|
@ -1733,7 +1694,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
|
||||
if len(cart_types) > 0:
|
||||
cart_type = cart_type_id
|
||||
#if (cart_type == 1): cart_type = 0
|
||||
if self.CONN.GetMode() == "DMG":
|
||||
self.cmbDMGCartridgeTypeResult.setCurrentIndex(cart_type)
|
||||
elif self.CONN.GetMode() == "AGB":
|
||||
|
|
@ -1746,7 +1706,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
else:
|
||||
msg_cart_type += "- {:s}<br>".format(supp_cart_types[0][cart_types[i]])
|
||||
msg_cart_type = msg_cart_type[:-4]
|
||||
#if msg_cart_type == "": msg_cart_type = "{:s}<br>".format(supp_cart_types[0][0])
|
||||
|
||||
except:
|
||||
pass
|
||||
|
|
@ -1779,11 +1738,10 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
msg_flash_size_s = ""
|
||||
msg_flash_id_s = ""
|
||||
msg_cfi_s = ""
|
||||
try_this = None
|
||||
found_supported = False
|
||||
is_generic = False
|
||||
if cart_type is not None:
|
||||
#(flash_id, cfi_s, _) = self.CONN.CheckFlashChip(limitVoltage=limitVoltage, cart_type=supp_cart_types[1][cart_type])
|
||||
#msg_cart_type_s = "<b>Cartridge Type:</b> Supported flash cartridge type (will be auto-selected)<br>"
|
||||
if len(cart_types) > 1:
|
||||
msg_cart_type_s = "<b>Cartridge Type:</b> {:s} (or compatible)<br>".format(msg_cart_type_used)
|
||||
else:
|
||||
|
|
@ -1796,16 +1754,28 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
msg_flash_size_s = "<b>ROM Size:</b> {:s}<br>".format(Util.formatFileSize(size, asInt=True))
|
||||
|
||||
else:
|
||||
#(flash_id, cfi_s, _) = self.CONN.CheckFlashChip(limitVoltage=limitVoltage)
|
||||
if (len(flash_id.split("\n")) > 2) and ((self.CONN.GetMode() == "DMG") or ("dacs_8m" in header and header["dacs_8m"] is not True)):
|
||||
msg_cart_type_s = "<b>Cartridge Type:</b> Unknown flash cartridge – Please submit the displayed information along with a picture of the cartridge’s circuit board."
|
||||
if ("[ 0/90]" in flash_id): msg_cart_type_s += " For ROM writing, you can give the option called “Generic Flash Cartridge (0/90)” a try."
|
||||
elif ("[ AAA/AA]" in flash_id): msg_cart_type_s += " For ROM writing, you can give the option called “Generic Flash Cartridge (AAA/AA)” a try."
|
||||
elif ("[ AAA/A9]" in flash_id): msg_cart_type_s += " For ROM writing, you can give the option called “Generic Flash Cartridge (AAA/A9)” a try."
|
||||
elif ("[WR / AAA/AA]" in flash_id): msg_cart_type_s += " For ROM writing, you can give the option called “Generic Flash Cartridge (WR/AAA/AA)” a try."
|
||||
elif ("[WR / AAA/A9]" in flash_id): msg_cart_type_s += " For ROM writing, you can give the option called “Generic Flash Cartridge (WR/AAA/A9)” a try."
|
||||
elif ("[WR / 555/AA]" in flash_id): msg_cart_type_s += " For ROM writing, you can give the option called “Generic Flash Cartridge (WR/555/AA)” a try."
|
||||
elif ("[WR / 555/A9]" in flash_id): msg_cart_type_s += " For ROM writing, you can give the option called “Generic Flash Cartridge (WR/555/A9)” a try."
|
||||
if ("[ 0/90]" in flash_id):
|
||||
try_this = "Generic Flash Cartridge (0/90)"
|
||||
elif ("[ AAA/AA]" in flash_id):
|
||||
try_this = "Generic Flash Cartridge (AAA/AA)"
|
||||
elif ("[ AAA/A9]" in flash_id):
|
||||
try_this = "Generic Flash Cartridge (AAA/A9)"
|
||||
elif ("[WR / AAA/AA]" in flash_id):
|
||||
try_this = "Generic Flash Cartridge (WR/AAA/AA)"
|
||||
elif ("[WR / AAA/A9]" in flash_id):
|
||||
try_this = "Generic Flash Cartridge (WR/AAA/A9)"
|
||||
elif ("[WR / 555/AA]" in flash_id):
|
||||
try_this = "Generic Flash Cartridge (WR/555/AA)"
|
||||
elif ("[WR / 555/A9]" in flash_id):
|
||||
try_this = "Generic Flash Cartridge (WR/555/A9)"
|
||||
elif ("[AUDIO/ AAA/AA]" in flash_id):
|
||||
try_this = "Generic Flash Cartridge (AUDIO/AAA/AA)"
|
||||
elif ("[AUDIO/ 555/AA]" in flash_id):
|
||||
try_this = "Generic Flash Cartridge (AUDIO/555/AA)"
|
||||
if try_this is not None:
|
||||
msg_cart_type_s += " For ROM writing, you can give the option called “{:s}” a try at your own risk.".format(try_this)
|
||||
msg_cart_type_s += "<br>"
|
||||
else:
|
||||
msg_cart_type_s = "<b>Cartridge Type:</b> Generic ROM Cartridge (not rewritable or not auto-detectable)<br>"
|
||||
|
|
@ -1869,12 +1839,19 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
button_ok = msgbox.addButton("&OK", QtWidgets.QMessageBox.ActionRole)
|
||||
msgbox.setDefaultButton(button_ok)
|
||||
msgbox.setEscapeButton(button_ok)
|
||||
if try_this is not None:
|
||||
button_try = msgbox.addButton(" &Try Generic Type ", QtWidgets.QMessageBox.ActionRole)
|
||||
button_try.setToolTip("{:s}".format(try_this))
|
||||
else:
|
||||
button_try = None
|
||||
|
||||
if not is_generic:
|
||||
msg_fw = "<br><span style=\"font-size: 8pt;\"><i>{:s} {:s} | {:s}</i></span><br>".format(APPNAME, VERSION, self.CONN.GetFullNameExtended())
|
||||
button_clipboard = msgbox.addButton(" &Copy to Clipboard ", QtWidgets.QMessageBox.ActionRole)
|
||||
else:
|
||||
msg_fw = ""
|
||||
button_clipboard = None
|
||||
|
||||
temp = "{:s}{:s}{:s}{:s}{:s}{:s}{:s}{:s}".format(msg, msg_header_s, msg_flash_size_s, msg_save_type_s, msg_flash_id_s, msg_cfi_s, msg_cart_type_s_detail, msg_fw)
|
||||
temp = temp[:-4]
|
||||
msgbox.setText(temp)
|
||||
|
|
@ -1886,6 +1863,13 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
doc.setHtml(temp)
|
||||
temp = doc.toPlainText()
|
||||
clipboard.setText(temp)
|
||||
elif msgbox.clickedButton() == button_try:
|
||||
if try_this in supp_cart_types[0]:
|
||||
cart_type = supp_cart_types[0].index(try_this)
|
||||
if self.CONN.GetMode() == "DMG":
|
||||
self.cmbDMGCartridgeTypeResult.setCurrentIndex(cart_type)
|
||||
elif self.CONN.GetMode() == "AGB":
|
||||
self.cmbAGBCartridgeTypeResult.setCurrentIndex(cart_type)
|
||||
|
||||
self.btnHeaderRefresh.setEnabled(True)
|
||||
self.btnDetectCartridge.setEnabled(True)
|
||||
|
|
|
|||
|
|
@ -61,12 +61,6 @@ class Flashcart:
|
|||
def GetMBC(self):
|
||||
if (self.CONFIG["type"].upper() == "AGB") or ("mbc" not in self.CONFIG): return False
|
||||
mbc = self.CONFIG["mbc"]
|
||||
#if mbc == 1: mbc = 0x03
|
||||
#elif mbc == 2: mbc = 0x06
|
||||
#elif mbc == 3: mbc = 0x13
|
||||
#elif mbc == 5: mbc = 0x1B
|
||||
#elif mbc == 6: mbc = 0x20
|
||||
#elif mbc == 7: mbc = 0x22
|
||||
return mbc
|
||||
|
||||
def FlashCommandsOnBank1(self):
|
||||
|
|
@ -86,7 +80,6 @@ class Flashcart:
|
|||
if buffer_size is False:
|
||||
return False
|
||||
else:
|
||||
#return True
|
||||
return ("buffer_write" in self.CONFIG["commands"])
|
||||
|
||||
def SupportsSingleWrite(self):
|
||||
|
|
@ -133,6 +126,9 @@ class Flashcart:
|
|||
cfi = self.ReadCFI()
|
||||
if cfi is False:
|
||||
print("CFI ERROR: Couldn’t retrieve buffer size from the cartridge.")
|
||||
if "single_write" in self.CONFIG["commands"]:
|
||||
del(self.CONFIG["commands"]["buffer_write"])
|
||||
print("Buffered write disabled.")
|
||||
return False
|
||||
if not "buffer_size" in cfi: return False
|
||||
buffer_size = cfi["buffer_size"]
|
||||
|
|
@ -197,11 +193,9 @@ class Flashcart:
|
|||
self.CONFIG["commands"]["read_cfi"] = [ [ 0xAA, 0x98 ] ]
|
||||
|
||||
if "read_cfi" in self.CONFIG["commands"]:
|
||||
#print(self.CONFIG["commands"]["read_cfi"])
|
||||
self.CartWrite(self.CONFIG["commands"]["read_cfi"])
|
||||
time.sleep(0.1)
|
||||
buffer = self.CartRead(0, 0x400)
|
||||
#print(buffer)
|
||||
self.Reset()
|
||||
cfi = CFI().Parse(buffer)
|
||||
if cfi is not False:
|
||||
|
|
@ -232,6 +226,9 @@ class Flashcart:
|
|||
cfi = self.ReadCFI()
|
||||
if cfi is False:
|
||||
print("CFI ERROR: Couldn’t retrieve sector size map from the cartridge.")
|
||||
if "chip_erase" in self.CONFIG["commands"]:
|
||||
del(self.CONFIG["commands"]["sector_erase"])
|
||||
print("Sector erase mode disabled.")
|
||||
return False
|
||||
sector_size = cfi["erase_sector_blocks"]
|
||||
if cfi["tb_boot_sector_raw"] == 0x03: sector_size.reverse()
|
||||
|
|
@ -276,8 +273,6 @@ class Flashcart:
|
|||
|
||||
def SectorErase(self, pos=0, buffer_pos=0):
|
||||
self.Reset(full_reset=False)
|
||||
#time_start = time.time()
|
||||
#if progress_fnc is not None: progress_fnc({"action":"ERASE", "time_start":time_start, "abortable":False})
|
||||
if "sector_erase" not in self.CONFIG["commands"]: return False
|
||||
if "sector_size" not in self.CONFIG: return False
|
||||
for i in range(0, len(self.CONFIG["commands"]["sector_erase"])):
|
||||
|
|
@ -330,7 +325,6 @@ class Flashcart:
|
|||
except:
|
||||
dprint("Warning: Sector map is smaller than expected.")
|
||||
self.SECTOR_POS -= 1
|
||||
#self.CONFIG["sector_size"][self.SECTOR_POS][0]
|
||||
return sector_size
|
||||
else:
|
||||
return self.CONFIG["sector_size"]
|
||||
|
|
@ -478,9 +472,6 @@ class CFI:
|
|||
return info
|
||||
|
||||
class Flashcart_DMG_MMSA(Flashcart):
|
||||
#def __init__(self, config={}, cart_write_fncptr=None, cart_read_fncptr=None):
|
||||
# super().__init__(config=config, cart_write_fncptr=cart_write_fncptr, cart_read_fncptr=cart_read_fncptr)
|
||||
|
||||
def ReadCFI(self):
|
||||
return False
|
||||
|
||||
|
|
@ -494,7 +485,6 @@ class Flashcart_DMG_MMSA(Flashcart):
|
|||
return True
|
||||
|
||||
def EraseHiddenSector(self, buffer):
|
||||
#time_start = time.time()
|
||||
if self.PROGRESS_FNCPTR is not None: self.PROGRESS_FNCPTR({"action":"SECTOR_ERASE", "sector_pos":0, "time_start":time.time(), "abortable":False})
|
||||
|
||||
self.UnlockForWriting()
|
||||
|
|
|
|||
221
FlashGBX/GBMemory.py
Normal file
221
FlashGBX/GBMemory.py
Normal file
|
|
@ -0,0 +1,221 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
|
||||
import datetime, struct, copy
|
||||
from . import Util
|
||||
from .RomFileDMG import RomFileDMG
|
||||
|
||||
class GBMemoryMap:
|
||||
MAP_DATA = bytearray([0xFF] * 0x80)
|
||||
IS_MENU = False
|
||||
|
||||
def __init__(self, rom=None):
|
||||
if rom is not None:
|
||||
self.ImportROM(rom)
|
||||
|
||||
def ImportROM(self, data):
|
||||
info = {"map":{}, "menu":{}}
|
||||
if len(data) < 0x180:
|
||||
return False
|
||||
info["rom_header"] = RomFileDMG(data[:0x180]).GetHeader()
|
||||
self.IS_MENU = (info["rom_header"]["game_title"] in ("NP M-MENU MENU", "DMG MULTI MENU "))
|
||||
|
||||
data = copy.deepcopy(data)
|
||||
if len(data) < 0x20000:
|
||||
data = bytearray(data) + bytearray([0xFF] * (0x20000 - len(data)))
|
||||
|
||||
if not self.IS_MENU:
|
||||
mbc_type = self.MapperToMBCType(info["rom_header"]["features_raw"])
|
||||
if mbc_type is False: return
|
||||
if len(data) <= 0x20000:
|
||||
rom_size = 0b010
|
||||
elif len(data) <= 0x40000:
|
||||
rom_size = 0b011
|
||||
elif len(data) <= 0x80000:
|
||||
rom_size = 0b100
|
||||
else:
|
||||
rom_size = 0b101
|
||||
|
||||
if info["rom_header"]["ram_size_raw"] not in Util.DMG_Header_RAM_Sizes_Map:
|
||||
sram_size = 0
|
||||
sram_type = 0b000
|
||||
else:
|
||||
sram_size = Util.DMG_Header_RAM_Sizes_Flasher_Map[Util.DMG_Header_RAM_Sizes_Map.index(info["rom_header"]["ram_size_raw"])]
|
||||
if sram_size == 0:
|
||||
sram_type = 0b000
|
||||
elif sram_size == 0x2000:
|
||||
sram_type = 0b010
|
||||
elif sram_size == 0x8000:
|
||||
sram_type = 0b011
|
||||
elif sram_size == 0x10000:
|
||||
sram_type = 0b100
|
||||
elif sram_size == 0x20000:
|
||||
sram_type = 0b101
|
||||
else:
|
||||
sram_type = 0b000
|
||||
|
||||
info["map"] = {
|
||||
"mbc_type":mbc_type,
|
||||
"rom_size":rom_size,
|
||||
"sram_type":sram_type,
|
||||
"rom_start_block":0,
|
||||
"ram_start_block":0,
|
||||
"raw":bytearray()
|
||||
}
|
||||
|
||||
info["menu"]["metadata"] = {}
|
||||
info["menu"]["metadata"]["f_size"] = int(len(data) / (128 * 1024))
|
||||
if info["map"]["sram_type"] == 0b000: # None
|
||||
info["menu"]["metadata"]["b_size"] = 0
|
||||
elif info["map"]["sram_type"] == 0b001: # SRAM MBC2 512 Byte
|
||||
info["menu"]["metadata"]["b_size"] = 64 #4
|
||||
elif info["map"]["sram_type"] == 0b010: # SRAM 8 KB
|
||||
info["menu"]["metadata"]["b_size"] = 64
|
||||
elif info["map"]["sram_type"] == 0b011: # SRAM 32 KB
|
||||
info["menu"]["metadata"]["b_size"] = 256
|
||||
elif info["map"]["sram_type"] == 0b100: # SRAM 64 KB
|
||||
info["menu"]["metadata"]["b_size"] = 512
|
||||
elif info["map"]["sram_type"] == 0b101: # SRAM 128 KB
|
||||
info["menu"]["metadata"]["b_size"] = 1024
|
||||
|
||||
info["menu"]["metadata"]["game_code"] = "{:s} -{:s}- ".format("CGB" if info["rom_header"]["cgb"] == 0xC0 else "DMG", " ").encode("ascii")
|
||||
info["menu"]["metadata"]["title"] = info["rom_header"]["game_title"].encode("ascii").ljust(0x2C)
|
||||
info["menu"]["metadata"]["timestamp"] = datetime.datetime.now().strftime('%Y/%m/%d%H:%M:%S').encode("ascii")
|
||||
info["menu"]["metadata"]["kiosk_id"] = "{:s} v{:s}".format(Util.APPNAME, Util.VERSION_PEP440).encode("ascii").ljust(24, b'\xFF')
|
||||
info["menu"]["raw"] = bytearray(0x56)
|
||||
data = info
|
||||
|
||||
keys = ["f_size", "b_size", "game_code", "title", "timestamp", "kiosk_id"]
|
||||
values = []
|
||||
for key in keys:
|
||||
values.append(data["menu"]["metadata"][key])
|
||||
buffer = struct.pack("=HH12s44s18s26s", *values)
|
||||
data["menu"]["raw"] = buffer
|
||||
|
||||
temp = 0
|
||||
temp |= (data["map"]["mbc_type"] & 0x7) << 29
|
||||
temp |= (data["map"]["rom_size"] & 0x7) << 26
|
||||
temp |= (data["map"]["sram_type"] & 0x7) << 23
|
||||
temp |= (data["map"]["rom_start_block"] & 0x7F) << 16
|
||||
temp |= (data["map"]["ram_start_block"] & 0x7F) << 8
|
||||
data["map"]["raw"] = temp
|
||||
|
||||
self.MAP_DATA[0x00:0x6E] = bytearray([0xFF] * 0x6E)
|
||||
self.MAP_DATA[0x7E:0x80] = bytearray([0x00] * 2)
|
||||
self.MAP_DATA[0:3] = struct.pack(">I", data["map"]["raw"])[:3]
|
||||
self.MAP_DATA[0x18:0x18+len(data["menu"]["raw"])] = data["menu"]["raw"]
|
||||
|
||||
elif info["rom_header"]["game_title"] == "NP M-MENU MENU":
|
||||
menu_items = []
|
||||
rom_offset = 0
|
||||
ram_offset = 0
|
||||
for i in range(0, 8):
|
||||
pos = 0x1C000 + (i * 0x200)
|
||||
menu_item = data[pos:pos+0x200]
|
||||
keys = ["menu_index", "f_offset", "b_offset", "f_size", "b_size", "game_code", "title", "title_gfx", "timestamp", "kiosk_id", "padding", "comment"]
|
||||
values = struct.unpack("=BBBHH12s44s384s18s8s23s16s", menu_item)
|
||||
info = dict(zip(keys, values))
|
||||
if info["menu_index"] == 0xFF: continue
|
||||
info["rom_data_offset"] = info["f_offset"] * (128 * 1024)
|
||||
info["rom_data_size"] = info["f_size"] * (128 * 1024)
|
||||
info["ram_data_offset"] = info["b_offset"] * (8 * 1024)
|
||||
info["ram_data_size"] = self.GetBlockSizeBackup(info["b_size"]) * (8 * 1024)
|
||||
del(info["title_gfx"])
|
||||
info["rom_start_block"] = int(rom_offset / 0x8000)
|
||||
rom_offset += info["rom_data_size"]
|
||||
info["ram_start_block"] = int(ram_offset / 0x800)
|
||||
ram_offset += info["ram_data_size"]
|
||||
info["rom_header"] = RomFileDMG(data[info["rom_data_offset"]:info["rom_data_offset"]+0x180]).GetHeader()
|
||||
mbc_type = self.MapperToMBCType(info["rom_header"]["features_raw"])
|
||||
if mbc_type is False: return
|
||||
|
||||
if info["rom_data_size"] <= 0x20000:
|
||||
rom_size = 0b010
|
||||
elif info["rom_data_size"] <= 0x40000:
|
||||
rom_size = 0b011
|
||||
elif info["rom_data_size"] <= 0x80000:
|
||||
rom_size = 0b100
|
||||
else:
|
||||
rom_size = 0b101
|
||||
|
||||
if info["rom_header"]["game_title"] == "NP M-MENU MENU" or info["rom_header"]["ram_size_raw"] not in Util.DMG_Header_RAM_Sizes_Map:
|
||||
sram_size = 0
|
||||
sram_type = 0b000
|
||||
else:
|
||||
sram_size = Util.DMG_Header_RAM_Sizes_Flasher_Map[Util.DMG_Header_RAM_Sizes_Map.index(info["rom_header"]["ram_size_raw"])]
|
||||
if sram_size == 0:
|
||||
sram_type = 0b000
|
||||
elif sram_size == 0x2000:
|
||||
sram_type = 0b010
|
||||
elif sram_size == 0x8000:
|
||||
sram_type = 0b011
|
||||
elif sram_size == 0x10000:
|
||||
sram_type = 0b100
|
||||
elif sram_size == 0x20000:
|
||||
sram_type = 0b101
|
||||
else:
|
||||
sram_type = 0b000
|
||||
|
||||
info["map"] = {
|
||||
"mbc_type":mbc_type,
|
||||
"rom_size":rom_size,
|
||||
"sram_type":sram_type,
|
||||
"rom_start_block":info["rom_start_block"],
|
||||
"ram_start_block":info["ram_start_block"],
|
||||
"raw":bytearray()
|
||||
}
|
||||
|
||||
temp = 0
|
||||
temp |= (info["map"]["mbc_type"] & 0x7) << 29
|
||||
temp |= (info["map"]["rom_size"] & 0x7) << 26
|
||||
temp |= (info["map"]["sram_type"] & 0x7) << 23
|
||||
temp |= (info["map"]["rom_start_block"] & 0x7F) << 16
|
||||
temp |= (info["map"]["ram_start_block"] & 0x7F) << 8
|
||||
info["map"]["raw"] = temp
|
||||
menu_items.append(info)
|
||||
|
||||
self.MAP_DATA[0x00:0x6E] = bytearray([0xFF] * 0x6E)
|
||||
self.MAP_DATA[0x7E:0x80] = bytearray([0x00] * 2)
|
||||
for i in range(0, len(menu_items)):
|
||||
pos = i * 3
|
||||
self.MAP_DATA[pos:pos+3] = struct.pack(">I", menu_items[i]["map"]["raw"])[:3]
|
||||
self.MAP_DATA[0x54:0x66] = struct.pack("=18s", datetime.datetime.now().strftime('%Y/%m/%d%H:%M:%S').encode("ascii"))
|
||||
self.MAP_DATA[0x66:0x7E] = struct.pack("=24s", "{:s} v{:s}".format(Util.APPNAME, Util.VERSION_PEP440).encode("ascii").ljust(24, b'\xFF'))
|
||||
|
||||
def MapperToMBCType(self, mbc):
|
||||
if mbc == 0x00: # ROM only
|
||||
mbc_type = 0
|
||||
elif mbc in (0x01, 0x02, 0x03): # MBC1
|
||||
mbc_type = 1
|
||||
elif mbc == 0x06: # MBC2
|
||||
mbc_type = 2
|
||||
elif mbc in (0x10, 0x13): # MBC3
|
||||
mbc_type = 3
|
||||
elif mbc in (0x19, 0x1A, 0x1B, 0x1C, 0x1E): # MBC5
|
||||
mbc_type = 5
|
||||
else:
|
||||
mbc_type = False
|
||||
return mbc_type
|
||||
|
||||
def GetBlockSizeBackup(self, b_size=None):
|
||||
if b_size == 0:
|
||||
b_size = 0
|
||||
elif b_size == 1:
|
||||
b_size = 1
|
||||
elif b_size == 64:
|
||||
b_size = 1
|
||||
elif b_size == 256:
|
||||
b_size = 4
|
||||
elif b_size == 1024:
|
||||
b_size = 16
|
||||
else:
|
||||
b_size = 4
|
||||
return b_size
|
||||
|
||||
def IsMenu(self):
|
||||
return self.IS_MENU
|
||||
|
||||
def GetMapData(self):
|
||||
if self.MAP_DATA == bytearray([0xFF] * 0x80): return False
|
||||
return self.MAP_DATA
|
||||
|
|
@ -708,9 +708,16 @@ class DMG_GMMC1(DMG_MBC5):
|
|||
|
||||
def CalcChecksum(self, buffer):
|
||||
header = RomFileDMG(buffer[:0x180]).GetHeader()
|
||||
target_chk_value = 0
|
||||
if header["game_title"] == "NP M-MENU MENU":
|
||||
target_sha1_value = "15f5d445c0b2fdf4221cf2a986a4a5cb8dfda131"
|
||||
target_chk_value = 0x19E8
|
||||
if hashlib.sha1(buffer[0:0x18000]).hexdigest() != "15f5d445c0b2fdf4221cf2a986a4a5cb8dfda131":
|
||||
elif header["game_title"] == "DMG MULTI MENU ":
|
||||
target_sha1_value = "b8949fb9c4343b2c04ad59064e9d1dd78a131366"
|
||||
target_chk_value = 0xC297
|
||||
|
||||
if target_chk_value != 0:
|
||||
if hashlib.sha1(buffer[0:0x18000]).hexdigest() != target_sha1_value:
|
||||
return 0
|
||||
elif buffer[0:0x180] == buffer[0x20000:0x20180]:
|
||||
return 1
|
||||
|
|
|
|||
|
|
@ -33,16 +33,18 @@ class RomFileDMG:
|
|||
return checksum
|
||||
|
||||
def CalcChecksumGlobal(self, fix=False):
|
||||
checksum = 0
|
||||
for i in range(0, len(self.ROMFILE), 2):
|
||||
if i != 0x14E:
|
||||
checksum = checksum + self.ROMFILE[i + 1]
|
||||
checksum = checksum + self.ROMFILE[i]
|
||||
|
||||
temp1 = self.ROMFILE[0x14E]
|
||||
temp2 = self.ROMFILE[0x14F]
|
||||
self.ROMFILE[0x14E] = 0
|
||||
self.ROMFILE[0x14F] = 0
|
||||
checksum = sum(self.ROMFILE) & 0xFFFF
|
||||
if fix:
|
||||
self.ROMFILE[0x14E] = checksum >> 8
|
||||
self.ROMFILE[0x14F] = checksum & 0xFF
|
||||
return checksum & 0xFFFF
|
||||
else:
|
||||
self.ROMFILE[0x14E] = temp1
|
||||
self.ROMFILE[0x14F] = temp2
|
||||
return checksum
|
||||
|
||||
def FixHeader(self):
|
||||
self.CalcChecksumHeader(True)
|
||||
|
|
@ -78,13 +80,13 @@ class RomFileDMG:
|
|||
data["features"] = "?"
|
||||
data["rom_size_raw"] = int(buffer[0x148])
|
||||
data["rom_size"] = "?"
|
||||
if buffer[0x148] in Util.DMG_Header_ROM_Sizes: data["rom_size"] = Util.DMG_Header_ROM_Sizes[buffer[0x148]]
|
||||
if buffer[0x148] < len(Util.DMG_Header_ROM_Sizes): data["rom_size"] = Util.DMG_Header_ROM_Sizes[buffer[0x148]]
|
||||
data["ram_size_raw"] = int(buffer[0x149])
|
||||
if data["features_raw"] == 0x05 or data["features_raw"] == 0x06:
|
||||
data["ram_size"] = 0x200
|
||||
else:
|
||||
data["ram_size"] = "?"
|
||||
if buffer[0x149] in Util.DMG_Header_RAM_Sizes:
|
||||
if buffer[0x149] < len(Util.DMG_Header_RAM_Sizes):
|
||||
data["ram_size"] = Util.DMG_Header_RAM_Sizes[buffer[0x149]]
|
||||
data["version"] = int(buffer[0x14C])
|
||||
data["header_checksum"] = int(buffer[0x14D])
|
||||
|
|
@ -107,6 +109,9 @@ class RomFileDMG:
|
|||
if data["features_raw"] == 0x19 and data["game_title"] == "NP M-MENU MENU" and data["header_checksum"] == 0xD3:
|
||||
data["features_raw"] = 0x105
|
||||
data["ram_size_raw"] = 0x04
|
||||
elif data["features_raw"] == 0x01 and data["game_title"] == "DMG MULTI MENU " and data["header_checksum"] == 0x36:
|
||||
data["features_raw"] = 0x105
|
||||
data["ram_size_raw"] = 0x04
|
||||
|
||||
# M161 (Mani 4 in 1)
|
||||
elif data["features_raw"] == 0x10 and data["game_title"] == "TETRIS SET" and data["header_checksum"] == 0x3F:
|
||||
|
|
@ -118,12 +123,16 @@ class RomFileDMG:
|
|||
data["features_raw"] == 0x11 and data["game_title"] == "GANBARUGA SET" and data["header_checksum"] == 0x90 or \
|
||||
data["features_raw"] == 0x11 and data["game_title"] == "RTYPE 2 SET" and data["header_checksum"] == 0x32:
|
||||
data["features_raw"] = 0x0B
|
||||
|
||||
|
||||
# Unlicensed 256M Mapper
|
||||
elif data["game_title"].upper() == "GB HICOL" and data["header_checksum"] in (0x4A, 0x49, 0xE9):
|
||||
elif (data["game_title"].upper() == "GB HICOL" and data["header_checksum"] in (0x4A, 0x49, 0xE9)) or \
|
||||
(data["game_title"] == "BennVenn" and data["header_checksum"] == 0x48):
|
||||
data["features_raw"] = 0x201
|
||||
data["rom_size_raw"] = 0x0A
|
||||
data["ram_size_raw"] = 0x201
|
||||
elif buffer[0x150:0x160].decode("ascii", "replace") == "256M ROM Builder":
|
||||
data["features_raw"] = 0x201
|
||||
data["ram_size_raw"] = 0x201
|
||||
|
||||
# Unlicensed Wisdom Tree Mapper
|
||||
elif hashlib.sha1(buffer[0x0:0x150]).digest() == bytearray([ 0xF5, 0xD2, 0x91, 0x7D, 0x5E, 0x5B, 0xAB, 0xD8, 0x5F, 0x0A, 0xC7, 0xBA, 0x56, 0xEB, 0x49, 0x8A, 0xBA, 0x12, 0x49, 0x13 ]): # Exodus / Joshua
|
||||
|
|
|
|||
|
|
@ -7,22 +7,21 @@ from enum import Enum
|
|||
|
||||
# Common constants
|
||||
APPNAME = "FlashGBX"
|
||||
VERSION_PEP440 = "3.6"
|
||||
VERSION_PEP440 = "3.7"
|
||||
VERSION = "v{:s}".format(VERSION_PEP440)
|
||||
DEBUG = False
|
||||
|
||||
AGB_Header_ROM_Sizes = [ "1 MB", "2 MB", "4 MB", "8 MB", "16 MB", "32 MB", "64 MB", "128 MB", "256 MB" ]
|
||||
AGB_Header_ROM_Sizes_Map = [ 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000 ]
|
||||
AGB_Header_Save_Types = [ "None", "4K EEPROM (512 Bytes)", "64K EEPROM (8 KB)", "256K SRAM (32 KB)", "512K SRAM (64 KB)", "1M SRAM (128 KB)", "512K FLASH (64 KB)", "1M FLASH (128 KB)", "8M DACS (1008 KB)" ]
|
||||
AGB_Header_Save_Sizes = [ 0, 512, 8192, 32768, 65536, 131072, 65536, 131072, 1032192 ]
|
||||
AGB_Header_Save_Types = [ "None", "4K EEPROM (512 Bytes)", "64K EEPROM (8 KB)", "256K SRAM/FRAM (32 KB)", "512K FLASH (64 KB)", "1M FLASH (128 KB)", "8M DACS (1008 KB)", "Unlicensed 512K SRAM (64 KB)", "Unlicensed 1M SRAM (128 KB)" ]
|
||||
AGB_Header_Save_Sizes = [ 0, 512, 8192, 32768, 65536, 131072, 1032192, 65536, 131072 ]
|
||||
AGB_Global_CRC32 = 0
|
||||
AGB_Flash_Save_Chips = { 0xBFD4:"SST 39VF512", 0x1F3D:"Atmel AT29LV512", 0xC21C:"Macronix MX29L512", 0x321B:"Panasonic MN63F805MNP", 0xC209:"Macronix MX29L010", 0x6213:"SANYO LE26FV10N1TS" }
|
||||
AGB_Flash_Save_Chips_Sizes = [ 0x10000, 0x10000, 0x10000, 0x10000, 0x20000, 0x20000 ]
|
||||
|
||||
DMG_Header_Mapper = { 0x00:'None', 0x01:'MBC1', 0x02:'MBC1+SRAM', 0x03:'MBC1+SRAM+BATTERY', 0x06:'MBC2+SRAM+BATTERY', 0x10:'MBC3+RTC+SRAM+BATTERY', 0x13:'MBC3+SRAM+BATTERY', 0x19:'MBC5', 0x1A:'MBC5+SRAM', 0x1B:'MBC5+SRAM+BATTERY', 0x1C:'MBC5+RUMBLE', 0x1E:'MBC5+RUMBLE+SRAM+BATTERY', 0x20:'MBC6+SRAM+FLASH+BATTERY', 0x22:'MBC7+ACCELEROMETER+EEPROM', 0x101:'MBC1M', 0x103:'MBC1M+SRAM+BATTERY', 0x0B:'MMM01', 0x0D:'MMM01+SRAM+BATTERY', 0xFC:'GBD+SRAM+BATTERY', 0x105:'G-MMC1+SRAM+BATTERY', 0x104:'M161', 0xFF:'HuC-1+IR+SRAM+BATTERY', 0xFE:'HuC-3+RTC+SRAM+BATTERY', 0xFD:'TAMA5+RTC+EEPROM', 0x201:'Unlicensed 256M Mapper', 0x202:'Unlicensed Wisdom Tree Mapper' }
|
||||
DMG_Header_ROM_Sizes = [ "32 KB", "64 KB", "128 KB", "256 KB", "512 KB", "1 MB", "2 MB", "4 MB", "8 MB", "16 MB", "32 MB" ]
|
||||
DMG_Header_ROM_Sizes_Map = [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x10, 0x20 ]
|
||||
#DMG_Header_ROM_Sizes_Flasher_Map = [ 2, 4, 8, 16, 32, 64, 128, 256, 512, 1024, 2048 ] # Number of ROM banks
|
||||
DMG_Header_ROM_Sizes_Map = [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A ]
|
||||
DMG_Header_ROM_Sizes_Flasher_Map = [ 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000 ]
|
||||
DMG_Header_RAM_Sizes = [ "None", "4K SRAM (512 Bytes)", "16K SRAM (2 KB)", "64K SRAM (8 KB)", "256K SRAM (32 KB)", "512K SRAM (64 KB)", "1M SRAM (128 KB)", "MBC6 SRAM+FLASH (1.03 MB)", "MBC7 2K EEPROM (256 Bytes)", "MBC7 4K EEPROM (512 Bytes)", "TAMA5 EEPROM (32 Bytes)", "Unlicensed 4M SRAM (512 KB)" ]
|
||||
DMG_Header_RAM_Sizes_Map = [ 0x00, 0x01, 0x01, 0x02, 0x03, 0x05, 0x04, 0x104, 0x101, 0x102, 0x103, 0x201 ]
|
||||
|
|
@ -66,7 +65,6 @@ class IniSettings():
|
|||
path = ""
|
||||
|
||||
if path == "":
|
||||
#buf = io.StringIO(ini)
|
||||
self.FILENAME = False
|
||||
self.SETTINGS = configparser.RawConfigParser()
|
||||
self.SETTINGS.read_string(ini)
|
||||
|
|
@ -258,7 +256,6 @@ def roundup(x):
|
|||
return math.ceil(x * d) / d
|
||||
|
||||
def formatFileSize(size, asInt=False, roundUp=False):
|
||||
#size = size / 1024
|
||||
if size == 1:
|
||||
return "{:d} Byte".format(size)
|
||||
elif size < 1024:
|
||||
|
|
@ -393,8 +390,8 @@ def ParseCFI(buffer):
|
|||
info["tb_boot_sector"] = "{:s} (0x{:02X})".format(temp[buffer[pri_address + 0x1E]], buffer[pri_address + 0x1E])
|
||||
except:
|
||||
info["tb_boot_sector"] = "0x{:02X}".format(buffer[pri_address + 0x1E])
|
||||
elif "{:s}{:s}{:s}".format(chr(buffer[0x214]), chr(buffer[0x216]), chr(buffer[0x218])) == "PRI":
|
||||
pass # TODO
|
||||
#elif "{:s}{:s}{:s}".format(chr(buffer[0x214]), chr(buffer[0x216]), chr(buffer[0x218])) == "PRI":
|
||||
# pass
|
||||
|
||||
info["device_size"] = int(math.pow(2, buffer[0x4E]))
|
||||
info["buffer_size"] = buffer[0x56] << 8 | buffer[0x54]
|
||||
|
|
|
|||
File diff suppressed because it is too large
Load Diff
|
|
@ -55,6 +55,22 @@
|
|||
[ null, null, null ],
|
||||
[ "SA", 0xFFFF, 0xFFFF ]
|
||||
],
|
||||
"chip_erase":[
|
||||
[ 0xAAA, 0xA9 ],
|
||||
[ 0x555, 0x56 ],
|
||||
[ 0xAAA, 0x80 ],
|
||||
[ 0xAAA, 0xA9 ],
|
||||
[ 0x555, 0x56 ],
|
||||
[ 0xAAA, 0x10 ]
|
||||
],
|
||||
"chip_erase_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ 0, 0xFFFF, 0xFFFF ]
|
||||
],
|
||||
"buffer_write":[
|
||||
[ 0xAAA, 0xA9 ],
|
||||
[ 0x555, 0x56 ],
|
||||
|
|
|
|||
56
FlashGBX/config/fc_AGB_MX29LV320ET.txt
Normal file
56
FlashGBX/config/fc_AGB_MX29LV320ET.txt
Normal file
|
|
@ -0,0 +1,56 @@
|
|||
{
|
||||
"type":"AGB",
|
||||
"names":[
|
||||
"B54 with MX29LV320ET",
|
||||
"B100 with MX29LV640ET"
|
||||
],
|
||||
"flash_ids":[
|
||||
[ 0xC2, 0x00, 0xA7, 0x22 ],
|
||||
[ 0xC2, 0x00, 0xC9, 0x22 ]
|
||||
],
|
||||
"voltage":3.3,
|
||||
"flash_size":0x400000,
|
||||
"chip_erase_timeout":200,
|
||||
"command_set":"AMD",
|
||||
"commands":{
|
||||
"reset":[
|
||||
[ 0, 0xF0 ]
|
||||
],
|
||||
"read_identifier":[
|
||||
[ 0xAAA, 0xAA ],
|
||||
[ 0x555, 0x55 ],
|
||||
[ 0xAAA, 0x90 ]
|
||||
],
|
||||
"read_cfi":[
|
||||
[ 0xAA, 0x98 ]
|
||||
],
|
||||
"chip_erase":[
|
||||
[ 0xAAA, 0xAA ],
|
||||
[ 0x555, 0x55 ],
|
||||
[ 0xAAA, 0x80 ],
|
||||
[ 0xAAA, 0xAA ],
|
||||
[ 0x555, 0x55 ],
|
||||
[ 0xAAA, 0x10 ]
|
||||
],
|
||||
"chip_erase_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ 0, 0xFFFF, 0xFFFF ]
|
||||
],
|
||||
"single_write":[
|
||||
[ 0xAAA, 0xAA ],
|
||||
[ 0x555, 0x55 ],
|
||||
[ 0xAAA, 0xA0 ],
|
||||
[ "PA", "PD" ]
|
||||
],
|
||||
"single_write_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ]
|
||||
]
|
||||
}
|
||||
}
|
||||
71
FlashGBX/config/fc_AGB_S29GL064.txt
Normal file
71
FlashGBX/config/fc_AGB_S29GL064.txt
Normal file
|
|
@ -0,0 +1,71 @@
|
|||
{
|
||||
"type":"AGB",
|
||||
"names":[
|
||||
"AGB-E05-01 with S29GL064"
|
||||
],
|
||||
"flash_ids":[
|
||||
[ 0x02, 0x00, 0x7D, 0x22 ]
|
||||
],
|
||||
"voltage":3.3,
|
||||
"flash_size":0x800000,
|
||||
"sector_size_from_cfi":true,
|
||||
"chip_erase_timeout":120,
|
||||
"command_set":"AMD",
|
||||
"commands":{
|
||||
"reset":[
|
||||
[ 0, 0xF0 ]
|
||||
],
|
||||
"read_identifier":[
|
||||
[ 0xAAA, 0xA9 ],
|
||||
[ 0x555, 0x56 ],
|
||||
[ 0xAAA, 0x90 ]
|
||||
],
|
||||
"read_cfi":[
|
||||
[ 0xAA, 0x98 ]
|
||||
],
|
||||
"sector_erase":[
|
||||
[ 0xAAA, 0xA9 ],
|
||||
[ 0x555, 0x56 ],
|
||||
[ 0xAAA, 0x80 ],
|
||||
[ 0xAAA, 0xA9 ],
|
||||
[ 0x555, 0x56 ],
|
||||
[ "SA", 0x30 ]
|
||||
],
|
||||
"sector_erase_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ "SA", 0xFFFF, 0xFFFF ]
|
||||
],
|
||||
"buffer_write":[
|
||||
[ 0xAAA, 0xA9 ],
|
||||
[ 0x555, 0x56 ],
|
||||
[ "SA", 0x26 ],
|
||||
[ "SA", "BS" ],
|
||||
[ "PA", "PD" ],
|
||||
[ "SA", 0x2A ]
|
||||
],
|
||||
"buffer_write_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ "SA", "PD", 0xFFFF ]
|
||||
],
|
||||
"single_write":[
|
||||
[ 0xAAA, 0xA9 ],
|
||||
[ 0x555, 0x56 ],
|
||||
[ 0xAAA, 0xA0 ],
|
||||
[ "PA", "PD" ]
|
||||
],
|
||||
"single_write_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ]
|
||||
]
|
||||
}
|
||||
}
|
||||
58
FlashGBX/config/fc_DMG_AM29F010_MBC1_AUDIO.txt
Normal file
58
FlashGBX/config/fc_DMG_AM29F010_MBC1_AUDIO.txt
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"type":"DMG",
|
||||
"names":[
|
||||
"DIY cart with MBC1 and AM29F010 @ AUDIO"
|
||||
],
|
||||
"flash_ids":[
|
||||
[ 0x01, 0x20 ]
|
||||
],
|
||||
"voltage":5,
|
||||
"flash_size":0x20000,
|
||||
"start_addr":0,
|
||||
"first_bank":1,
|
||||
"write_pin":"AUDIO",
|
||||
"chip_erase_timeout":60,
|
||||
"mbc":0x03,
|
||||
"command_set":"AMD",
|
||||
"commands":{
|
||||
"reset":[
|
||||
[ 0, 0xF0 ]
|
||||
],
|
||||
"read_identifier":[
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0x90 ]
|
||||
],
|
||||
"read_cfi":[
|
||||
[ 0x555, 0x98 ]
|
||||
],
|
||||
"chip_erase":[
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0x80 ],
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0x10 ]
|
||||
],
|
||||
"chip_erase_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ 0, 0xFF, 0xFF ]
|
||||
],
|
||||
"single_write":[
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0xA0 ],
|
||||
[ "PA", "PD" ]
|
||||
],
|
||||
"single_write_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ]
|
||||
]
|
||||
}
|
||||
}
|
||||
58
FlashGBX/config/fc_DMG_AM29F040_MBC1_AUDIO.txt
Normal file
58
FlashGBX/config/fc_DMG_AM29F040_MBC1_AUDIO.txt
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"type":"DMG",
|
||||
"names":[
|
||||
"DIY cart with MBC1 and AM29F040 @ AUDIO"
|
||||
],
|
||||
"flash_ids":[
|
||||
[ 0x01, 0xA4 ]
|
||||
],
|
||||
"voltage":5,
|
||||
"flash_size":0x80000,
|
||||
"start_addr":0,
|
||||
"first_bank":1,
|
||||
"write_pin":"AUDIO",
|
||||
"chip_erase_timeout":60,
|
||||
"mbc":0x03,
|
||||
"command_set":"AMD",
|
||||
"commands":{
|
||||
"reset":[
|
||||
[ 0, 0xF0 ]
|
||||
],
|
||||
"read_identifier":[
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0x90 ]
|
||||
],
|
||||
"read_cfi":[
|
||||
[ 0x555, 0x98 ]
|
||||
],
|
||||
"chip_erase":[
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0x80 ],
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0x10 ]
|
||||
],
|
||||
"chip_erase_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ 0, 0xFF, 0xFF ]
|
||||
],
|
||||
"single_write":[
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0xA0 ],
|
||||
[ "PA", "PD" ]
|
||||
],
|
||||
"single_write_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ]
|
||||
]
|
||||
}
|
||||
}
|
||||
58
FlashGBX/config/fc_DMG_AM29F040_MBC1_WR.txt
Normal file
58
FlashGBX/config/fc_DMG_AM29F040_MBC1_WR.txt
Normal file
|
|
@ -0,0 +1,58 @@
|
|||
{
|
||||
"type":"DMG",
|
||||
"names":[
|
||||
"DIY cart with MBC1 and AM29F040 @ WR"
|
||||
],
|
||||
"flash_ids":[
|
||||
[ 0x01, 0xA4 ]
|
||||
],
|
||||
"voltage":5,
|
||||
"flash_size":0x80000,
|
||||
"start_addr":0,
|
||||
"first_bank":1,
|
||||
"mbc":0x03,
|
||||
"write_pin":"WR",
|
||||
"chip_erase_timeout":15,
|
||||
"command_set":"AMD",
|
||||
"commands":{
|
||||
"reset":[
|
||||
[ 0, 0xF0 ]
|
||||
],
|
||||
"read_identifier":[
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0x90 ]
|
||||
],
|
||||
"read_cfi":[
|
||||
[ 0x555, 0x98 ]
|
||||
],
|
||||
"chip_erase":[
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0x80 ],
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0x10 ]
|
||||
],
|
||||
"chip_erase_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ 0, 0xFF, 0xFF ]
|
||||
],
|
||||
"single_write":[
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0xA0 ],
|
||||
[ "PA", "PD" ]
|
||||
],
|
||||
"single_write_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ]
|
||||
]
|
||||
}
|
||||
}
|
||||
59
FlashGBX/config/fc_DMG_AM29F080_MBC1_AUDIO.txt
Normal file
59
FlashGBX/config/fc_DMG_AM29F080_MBC1_AUDIO.txt
Normal file
|
|
@ -0,0 +1,59 @@
|
|||
{
|
||||
"type":"DMG",
|
||||
"names":[
|
||||
"DIY cart with MBC1 and AM29F080 @ AUDIO"
|
||||
],
|
||||
"flash_ids":[
|
||||
[ 0x20, 0xF1 ],
|
||||
[ 0x01, 0xD5 ]
|
||||
],
|
||||
"voltage":5,
|
||||
"flash_size":0x100000,
|
||||
"start_addr":0,
|
||||
"first_bank":1,
|
||||
"write_pin":"AUDIO",
|
||||
"chip_erase_timeout":60,
|
||||
"mbc":0x03,
|
||||
"command_set":"AMD",
|
||||
"commands":{
|
||||
"reset":[
|
||||
[ 0, 0xF0 ]
|
||||
],
|
||||
"read_identifier":[
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0x90 ]
|
||||
],
|
||||
"read_cfi":[
|
||||
[ 0x555, 0x98 ]
|
||||
],
|
||||
"chip_erase":[
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0x80 ],
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0x10 ]
|
||||
],
|
||||
"chip_erase_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ 0, 0xFF, 0xFF ]
|
||||
],
|
||||
"single_write":[
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0xA0 ],
|
||||
[ "PA", "PD" ]
|
||||
],
|
||||
"single_write_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ]
|
||||
]
|
||||
}
|
||||
}
|
||||
54
FlashGBX/config/fc_DMG_Generic_AUDIO_555_AA.txt
Normal file
54
FlashGBX/config/fc_DMG_Generic_AUDIO_555_AA.txt
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"type":"DMG",
|
||||
"names":[
|
||||
"Generic Flash Cartridge (AUDIO/555/AA)"
|
||||
],
|
||||
"voltage":3.3,
|
||||
"voltage_variants":true,
|
||||
"start_addr":0,
|
||||
"first_bank":1,
|
||||
"write_pin":"AUDIO",
|
||||
"chip_erase_timeout":120,
|
||||
"command_set":"AMD",
|
||||
"commands":{
|
||||
"reset":[
|
||||
[ 0, 0xF0 ]
|
||||
],
|
||||
"read_identifier":[
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0x90 ]
|
||||
],
|
||||
"read_cfi":[
|
||||
[ 0x555, 0x98 ]
|
||||
],
|
||||
"chip_erase":[
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0x80 ],
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0x10 ]
|
||||
],
|
||||
"chip_erase_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ 0, 0xFF, 0xFF ]
|
||||
],
|
||||
"single_write":[
|
||||
[ 0x555, 0xAA ],
|
||||
[ 0x2AA, 0x55 ],
|
||||
[ 0x555, 0xA0 ],
|
||||
[ "PA", "PD" ]
|
||||
],
|
||||
"single_write_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ]
|
||||
]
|
||||
}
|
||||
}
|
||||
54
FlashGBX/config/fc_DMG_Generic_AUDIO_AAA_AA.txt
Normal file
54
FlashGBX/config/fc_DMG_Generic_AUDIO_AAA_AA.txt
Normal file
|
|
@ -0,0 +1,54 @@
|
|||
{
|
||||
"type":"DMG",
|
||||
"names":[
|
||||
"Generic Flash Cartridge (AUDIO/AAA/AA)"
|
||||
],
|
||||
"voltage":3.3,
|
||||
"voltage_variants":true,
|
||||
"start_addr":0,
|
||||
"first_bank":1,
|
||||
"write_pin":"AUDIO",
|
||||
"chip_erase_timeout":120,
|
||||
"command_set":"AMD",
|
||||
"commands":{
|
||||
"reset":[
|
||||
[ 0, 0xF0 ]
|
||||
],
|
||||
"read_identifier":[
|
||||
[ 0xAAA, 0xAA ],
|
||||
[ 0x555, 0x55 ],
|
||||
[ 0xAAA, 0x90 ]
|
||||
],
|
||||
"read_cfi":[
|
||||
[ 0xAAA, 0x98 ]
|
||||
],
|
||||
"chip_erase":[
|
||||
[ 0xAAA, 0xAA ],
|
||||
[ 0x555, 0x55 ],
|
||||
[ 0xAAA, 0x80 ],
|
||||
[ 0xAAA, 0xAA ],
|
||||
[ 0x555, 0x55 ],
|
||||
[ 0xAAA, 0x10 ]
|
||||
],
|
||||
"chip_erase_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ 0, 0xFF, 0xFF ]
|
||||
],
|
||||
"single_write":[
|
||||
[ 0xAAA, 0xAA ],
|
||||
[ 0x555, 0x55 ],
|
||||
[ 0xAAA, 0xA0 ],
|
||||
[ "PA", "PD" ]
|
||||
],
|
||||
"single_write_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -15,6 +15,7 @@
|
|||
[ 0x04, 0x04, 0x7D, 0x7D ]
|
||||
],
|
||||
"voltage":3.3,
|
||||
"voltage_variants":true,
|
||||
"flash_size":0x400000,
|
||||
"start_addr":0x4000,
|
||||
"first_bank":0,
|
||||
|
|
|
|||
|
|
@ -62,8 +62,8 @@
|
|||
[ "SA", 0xFF, 0xFF ]
|
||||
],
|
||||
"buffer_write":[
|
||||
[ 0x4AAA, 0xA9 ],
|
||||
[ 0x4555, 0x56 ],
|
||||
[ 0xAAA, 0xA9 ],
|
||||
[ 0x555, 0x56 ],
|
||||
[ "SA", 0x26 ],
|
||||
[ "SA", "BS" ],
|
||||
[ "PA", "PD" ],
|
||||
|
|
|
|||
|
|
@ -9,10 +9,6 @@
|
|||
"start_addr":0x4000,
|
||||
"first_bank":1,
|
||||
"write_pin":"WR",
|
||||
"sector_size":[
|
||||
[0x2000, 8],
|
||||
[0x10000, 63]
|
||||
],
|
||||
"chip_erase_timeout":40,
|
||||
"mbc":0x03,
|
||||
"pulse_reset_after_write":true,
|
||||
|
|
|
|||
55
FlashGBX/config/fc_DMG_SST39SF040_MBC1_AUDIO.txt
Normal file
55
FlashGBX/config/fc_DMG_SST39SF040_MBC1_AUDIO.txt
Normal file
|
|
@ -0,0 +1,55 @@
|
|||
{
|
||||
"type":"DMG",
|
||||
"names":[
|
||||
"DIY cart with MBC1 and SST39SF040 @ AUDIO"
|
||||
],
|
||||
"flash_ids":[
|
||||
[ 0xBF, 0xB7, 0x01, 0xFF ]
|
||||
],
|
||||
"voltage":5,
|
||||
"flash_size":0x80000,
|
||||
"start_addr":0,
|
||||
"first_bank":1,
|
||||
"flash_commands_on_bank_1":true,
|
||||
"write_pin":"AUDIO",
|
||||
"chip_erase_timeout":30,
|
||||
"command_set":"AMD",
|
||||
"commands":{
|
||||
"reset":[
|
||||
[ 0, 0xF0 ]
|
||||
],
|
||||
"read_identifier":[
|
||||
[ 0x5555, 0xAA ],
|
||||
[ 0x2AAA, 0x55 ],
|
||||
[ 0x5555, 0x90 ]
|
||||
],
|
||||
"chip_erase":[
|
||||
[ 0x5555, 0xAA ],
|
||||
[ 0x2AAA, 0x55 ],
|
||||
[ 0x5555, 0x80 ],
|
||||
[ 0x5555, 0xAA ],
|
||||
[ 0x2AAA, 0x55 ],
|
||||
[ 0x5555, 0x10 ]
|
||||
],
|
||||
"chip_erase_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ 0, 0xFF, 0xFF ]
|
||||
],
|
||||
"single_write":[
|
||||
[ 0x5555, 0xAA ],
|
||||
[ 0x2AAA, 0x55 ],
|
||||
[ 0x5555, 0xA0 ],
|
||||
[ "PA", "PD" ]
|
||||
],
|
||||
"single_write_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -145,13 +145,11 @@ class FirmwareUpdaterWindow(QtWidgets.QDialog):
|
|||
rowDeviceInfo2 = QtWidgets.QHBoxLayout()
|
||||
self.lblDevicePCBVer = QtWidgets.QLabel("PCB version:")
|
||||
self.lblDevicePCBVer.setMinimumWidth(120)
|
||||
#self.lblDevicePCBVerResult = QtWidgets.QLabel("v1.4")
|
||||
self.optDevicePCBVer14 = QtWidgets.QRadioButton("v1.4")
|
||||
self.connect(self.optDevicePCBVer14, QtCore.SIGNAL("clicked()"), self.SetPCBVersion)
|
||||
self.optDevicePCBVer14a = QtWidgets.QRadioButton("v1.4a")
|
||||
self.connect(self.optDevicePCBVer14a, QtCore.SIGNAL("clicked()"), self.SetPCBVersion)
|
||||
rowDeviceInfo2.addWidget(self.lblDevicePCBVer)
|
||||
#rowDeviceInfo2.addWidget(self.lblDevicePCBVerResult)
|
||||
rowDeviceInfo2.addWidget(self.optDevicePCBVer14)
|
||||
rowDeviceInfo2.addWidget(self.optDevicePCBVer14a)
|
||||
rowDeviceInfo2.addStretch(1)
|
||||
|
|
@ -216,7 +214,6 @@ class FirmwareUpdaterWindow(QtWidgets.QDialog):
|
|||
|
||||
self.lblDeviceNameResult.setText(self.DEV_NAME)
|
||||
self.lblDeviceFWVerResult.setText(self.FW_VER)
|
||||
#self.lblDevicePCBVerResult.setText(self.PCB_VER)
|
||||
if self.PCB_VER == "v1.4":
|
||||
self.optDevicePCBVer14.setChecked(True)
|
||||
elif self.PCB_VER == "v1.4a":
|
||||
|
|
@ -239,7 +236,7 @@ class FirmwareUpdaterWindow(QtWidgets.QDialog):
|
|||
self.OFW_BUILDTS = self.INI.GetValue("fw_buildts")
|
||||
self.OFW_TEXT = self.INI.GetValue("fw_text")
|
||||
|
||||
self.lblDeviceFWVer2Result.setText("{:s} (dated {:s})".format(self.OFW_VER, datetime.datetime.fromtimestamp(int(self.OFW_BUILDTS)).astimezone().replace(microsecond=0).isoformat()))
|
||||
self.lblDeviceFWVer2Result.setText("{:s} ({:s})".format(self.OFW_VER, datetime.datetime.fromtimestamp(int(self.OFW_BUILDTS)).astimezone().replace(microsecond=0).isoformat()))
|
||||
|
||||
def run(self):
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -10,6 +10,7 @@ from .RomFileAGB import RomFileAGB
|
|||
from .Mapper import DMG_MBC, AGB_GPIO
|
||||
from .Flashcart import Flashcart, Flashcart_DMG_MMSA
|
||||
from .Util import ANSI, dprint, bitswap, ParseCFI
|
||||
from .GBMemory import GBMemoryMap
|
||||
from . import Util
|
||||
|
||||
class GbxDevice:
|
||||
|
|
@ -93,6 +94,7 @@ class GbxDevice:
|
|||
WORKER = None
|
||||
INFO = { "action":None, "last_action":None }
|
||||
ERROR = False
|
||||
ERROR_ARGS = {}
|
||||
CANCEL = False
|
||||
CANCEL_ARGS = {}
|
||||
SIGNAL = None
|
||||
|
|
@ -119,7 +121,6 @@ class GbxDevice:
|
|||
for i in range(0, len(comports)):
|
||||
if comports[i].vid == 0x1A86 and comports[i].pid == 0x7523:
|
||||
ports.append(comports[i].device)
|
||||
#break
|
||||
if len(ports) == 0: return False
|
||||
|
||||
for i in range(0, len(ports)):
|
||||
|
|
@ -301,7 +302,7 @@ class GbxDevice:
|
|||
else:
|
||||
s = "{:s}{:d}".format(self.FW["cfw_id"], self.FW["fw_ver"])
|
||||
if more:
|
||||
s += " (dated {:s})".format(self.FW["fw_dt"])
|
||||
s += " ({:s})".format(self.FW["fw_dt"])
|
||||
return s
|
||||
|
||||
def GetPCBVersion(self):
|
||||
|
|
@ -316,7 +317,7 @@ class GbxDevice:
|
|||
|
||||
def GetFullNameExtended(self, more=False):
|
||||
if more:
|
||||
return "{:s} – Firmware {:s} ({:s}) (dated {:s}) at {:.1f}M baud".format(self.GetFullName(), self.GetFirmwareVersion(), self.PORT, self.FW["fw_dt"], self.BAUDRATE/1000/1000)
|
||||
return "{:s} – Firmware {:s} ({:s}) on {:s} at {:.1f}M baud".format(self.GetFullName(), self.GetFirmwareVersion(), self.FW["fw_dt"], self.PORT, self.BAUDRATE/1000/1000)
|
||||
else:
|
||||
return "{:s} – Firmware {:s} ({:s})".format(self.GetFullName(), self.GetFirmwareVersion(), self.PORT)
|
||||
|
||||
|
|
@ -356,10 +357,14 @@ class GbxDevice:
|
|||
tb_stack = traceback.extract_stack()
|
||||
stack = tb_stack[len(tb_stack)-2] # caller only
|
||||
if stack.name == "_write": stack = tb_stack[len(tb_stack)-3]
|
||||
print("{:s}Waiting for confirmation from the device has failed. (Called from {:s}(), line {:d}){:s}\n".format(ANSI.RED, stack.name, stack.lineno, ANSI.RESET))
|
||||
self.CANCEL = True
|
||||
self.CANCEL_ARGS = {"info_type":"msgbox_critical", "info_msg":"An error occured while waiting for confirmation from the device. Please make sure that the cartridge contacts are clean, re-connect the device and try again from the beginning."}
|
||||
if buffer is False:
|
||||
dprint("Timeout error ({:s}(), line {:d})".format(stack.name, stack.lineno))
|
||||
self.CANCEL_ARGS.update({"info_type":"msgbox_critical", "info_msg":"A timeout error has occured at {:s}() in line {:d}. Please make sure that the cartridge contacts are clean, re-connect the device and try again from the beginning.".format(stack.name, stack.lineno)})
|
||||
else:
|
||||
dprint("Communication error ({:s}(), line {:d})".format(stack.name, stack.lineno))
|
||||
self.CANCEL_ARGS.update({"info_type":"msgbox_critical", "info_msg":"A communication error has occured at {:s}() in line {:d}. Please make sure that the cartridge contacts are clean, re-connect the device and try again from the beginning.".format(stack.name, stack.lineno)})
|
||||
self.ERROR = True
|
||||
self.CANCEL = True
|
||||
return False
|
||||
|
||||
return buffer
|
||||
|
|
@ -666,18 +671,16 @@ class GbxDevice:
|
|||
if mbc == 0x20: # MBC6
|
||||
save_size = 1081344
|
||||
save_type = 7
|
||||
(cart_types, cart_type_id, flash_id, cfi_s, cfi) = self.AutoDetectFlash(limitVoltage=limitVoltage)
|
||||
return (info, save_size, save_type, save_chip, sram_unstable, cart_types, cart_type_id, cfi_s, cfi, flash_id)
|
||||
elif mbc == 0x22: # MBC7
|
||||
max_size = 512
|
||||
elif mbc == 0xFD: # TAMA5
|
||||
save_size = 32
|
||||
save_type = 10
|
||||
(cart_types, cart_type_id, flash_id, cfi_s, cfi) = self.AutoDetectFlash(limitVoltage=limitVoltage)
|
||||
return (info, save_size, save_type, save_chip, sram_unstable, cart_types, cart_type_id, cfi_s, cfi, flash_id)
|
||||
args = { 'mode':2, 'path':None, 'mbc':mbc, 'save_type':max_size, 'rtc':False }
|
||||
elif self.MODE == "AGB":
|
||||
args = { 'mode':2, 'path':None, 'mbc':mbc, 'save_type':5, 'rtc':False }
|
||||
args = { 'mode':2, 'path':None, 'mbc':mbc, 'save_type':8, 'rtc':False }
|
||||
|
||||
ret = self._BackupRestoreRAM(args=args)
|
||||
|
||||
|
|
@ -712,18 +715,25 @@ class GbxDevice:
|
|||
save_size = Util.AGB_Flash_Save_Chips_Sizes[list(Util.AGB_Flash_Save_Chips).index(flash_save_id)]
|
||||
save_chip = Util.AGB_Flash_Save_Chips[flash_save_id]
|
||||
if save_size == 131072:
|
||||
save_type = 7
|
||||
save_type = 5
|
||||
elif save_size == 65536:
|
||||
save_type = 6
|
||||
save_type = 4
|
||||
except:
|
||||
pass
|
||||
|
||||
if save_type is None:
|
||||
if info["dacs_8m"] is True:
|
||||
save_size = 1032192
|
||||
save_type = 8
|
||||
elif save_size > 256:
|
||||
save_type = Util.AGB_Header_Save_Sizes.index(save_size)
|
||||
save_type = 6
|
||||
elif save_size > 256: # SRAM
|
||||
if save_size == 131072:
|
||||
save_type = 8
|
||||
elif save_size == 65536:
|
||||
save_type = 7
|
||||
elif save_size == 32768:
|
||||
save_type = 3
|
||||
else:
|
||||
save_type = Util.AGB_Header_Save_Sizes.index(save_size)
|
||||
else:
|
||||
dprint("Testing EEPROM")
|
||||
# Check for 4K EEPROM
|
||||
|
|
@ -745,7 +755,6 @@ class GbxDevice:
|
|||
save_size = 512
|
||||
|
||||
self._write(self.DEVICE_CMD["DMG_MBC_RESET"], wait=True)
|
||||
#if self.CanPowerCycleCart(): self.CartPowerCycle()
|
||||
self.INFO["last_action"] = 0
|
||||
self.INFO["action"] = None
|
||||
|
||||
|
|
@ -880,7 +889,6 @@ class GbxDevice:
|
|||
if isinstance(temp, int): temp = bytearray([temp])
|
||||
if temp is False or len(temp) != length: return bytearray()
|
||||
buffer += temp
|
||||
#if self.INFO["action"] == self.ACTIONS["SAVE_READ"] and not self.NO_PROG_UPDATE:
|
||||
if not self.NO_PROG_UPDATE:
|
||||
self.SetProgress({"action":"READ", "bytes_added":len(temp)})
|
||||
|
||||
|
|
@ -899,7 +907,6 @@ class GbxDevice:
|
|||
temp = self._read(length)
|
||||
if isinstance(temp, int): temp = bytearray([temp])
|
||||
buffer += temp
|
||||
#if self.INFO["action"] == self.ACTIONS["SAVE_READ"] and not self.NO_PROG_UPDATE:
|
||||
if not self.NO_PROG_UPDATE:
|
||||
self.SetProgress({"action":"READ", "bytes_added":len(temp)})
|
||||
|
||||
|
|
@ -1000,7 +1007,6 @@ class GbxDevice:
|
|||
self._cart_write(address + length - 1, 0x00)
|
||||
while True:
|
||||
sr = self._cart_read(address + length - 1)
|
||||
#print("sr=0x{:X}".format(sr))
|
||||
if sr == 0x80: break
|
||||
time.sleep(0.001)
|
||||
|
||||
|
|
@ -1092,7 +1098,8 @@ class GbxDevice:
|
|||
ret = self._write(data, wait=True)
|
||||
|
||||
if ret not in (0x01, 0x03):
|
||||
print("{:s}Flash error at 0x{:X} in iteration {:d} of {:d} while trying to write a total of 0x{:X} bytes (response = {:s}){:s}".format(ANSI.RED, address, i, num, len(buffer), str(ret), ANSI.RESET))
|
||||
dprint("Flash error at 0x{:X} in iteration {:d} of {:d} while trying to write a total of 0x{:X} bytes (response = {:s})".format(address, i, num, len(buffer), str(ret)))
|
||||
self.ERROR_ARGS = { "iteration":i }
|
||||
self.SKIPPING = False
|
||||
return False
|
||||
pos += len(data)
|
||||
|
|
@ -1190,7 +1197,6 @@ class GbxDevice:
|
|||
self._cart_write(address + length - 1, 0xFF)
|
||||
while True:
|
||||
sr = self._cart_read(address + length - 1)
|
||||
#print("sr=0x{:X}".format(sr))
|
||||
if sr == 0x80: break
|
||||
time.sleep(0.001)
|
||||
|
||||
|
|
@ -1203,10 +1209,6 @@ class GbxDevice:
|
|||
|
||||
def WriteROM_DMG_MBC5_32M_FLASH(self, address, buffer, bank):
|
||||
length = len(buffer)
|
||||
#if (self.FW["pcb_ver"] not in (5, 6, 101) or self.FW["fw_ver"] < 5):
|
||||
# max_length = 128
|
||||
#else:
|
||||
# max_length = 256
|
||||
max_length = 128
|
||||
num = math.ceil(length / max_length)
|
||||
if length > max_length: length = max_length
|
||||
|
|
@ -1290,7 +1292,6 @@ class GbxDevice:
|
|||
dprint("*** Now checking: {:s}\n".format(flashcart_meta["names"][0]))
|
||||
|
||||
if self.MODE == "DMG":
|
||||
#self._set_fw_variable("FLASH_COMMANDS_BANK_1", "flash_commands_on_bank_1" in flashcart_meta)
|
||||
if flashcart_meta["write_pin"] == "WR":
|
||||
we = 0x01 # FLASH_WE_PIN_WR
|
||||
elif flashcart_meta["write_pin"] in ("AUDIO", "VIN"):
|
||||
|
|
@ -1396,7 +1397,6 @@ class GbxDevice:
|
|||
if "method" in cfi: break
|
||||
for method in flash_commands:
|
||||
if self.MODE == "DMG":
|
||||
#self._set_fw_variable("FLASH_COMMANDS_BANK_1", "flash_commands_on_bank_1" in flashcart_meta)
|
||||
if we == "WR":
|
||||
self._set_fw_variable("FLASH_WE_PIN", 0x01) # FLASH_WE_PIN_WR
|
||||
elif we in ("AUDIO", "VIN"):
|
||||
|
|
@ -1555,7 +1555,7 @@ class GbxDevice:
|
|||
if not line_exists: flash_id_lines.append([method_string, flash_id])
|
||||
for i in range(0, len(method['reset'])):
|
||||
self._cart_write(method['reset'][i][0], method['reset'][i][1], flashcart=True)
|
||||
|
||||
|
||||
if self.MODE == "DMG":
|
||||
self._write(self.DEVICE_CMD["SET_VOLTAGE_5V"])
|
||||
time.sleep(0.25)
|
||||
|
|
@ -1572,7 +1572,7 @@ class GbxDevice:
|
|||
flash_id += "\n"
|
||||
|
||||
flash_id = rom_string + flash_id
|
||||
self._set_fw_variable("FLASH_WE_PIN", 0x02) # Set AUDIO back to high
|
||||
#self._set_fw_variable("FLASH_WE_PIN", 0x02) # Set AUDIO back to high
|
||||
return (flash_id, cfi_info, cfi)
|
||||
|
||||
#################################################################
|
||||
|
|
@ -1612,7 +1612,7 @@ class GbxDevice:
|
|||
if len(args["path"]) > 0:
|
||||
file = open(args["path"], "wb")
|
||||
|
||||
self.FAST_READ = True #args["fast_read_mode"]
|
||||
self.FAST_READ = True
|
||||
|
||||
flashcart = False
|
||||
supported_carts = list(self.SUPPORTED_CARTS[self.MODE].values())
|
||||
|
|
@ -1643,9 +1643,7 @@ class GbxDevice:
|
|||
else:
|
||||
_mbc.EnableMapper()
|
||||
|
||||
#rom_banks = args['rom_banks']
|
||||
rom_size = args["rom_size"]
|
||||
#if _mbc.GetName() in ("MBC6", "M161", "Wisdom Tree"): rom_banks = _mbc.GetROMBanks(args['rom_banks'] * 0x4000)
|
||||
rom_banks = _mbc.GetROMBanks(rom_size)
|
||||
size = _mbc.GetROMSize()
|
||||
|
||||
|
|
@ -1659,7 +1657,6 @@ class GbxDevice:
|
|||
if "verify_write" in args:
|
||||
rom_banks = math.ceil(len(args["verify_write"]) / cart_type["flash_bank_size"])
|
||||
else:
|
||||
#rom_banks = int(min(size, cart_type["flash_size"]) / cart_type["flash_bank_size"])
|
||||
rom_banks = math.ceil(size / cart_type["flash_bank_size"])
|
||||
else:
|
||||
rom_banks = 1
|
||||
|
|
@ -1706,6 +1703,7 @@ class GbxDevice:
|
|||
if file is not None: file.close()
|
||||
except:
|
||||
pass
|
||||
if self.CanPowerCycleCart(): self.CartPowerCycle()
|
||||
return
|
||||
|
||||
if (self.MODE == "AGB" and self.INFO["3d_memory"]):
|
||||
|
|
@ -1802,7 +1800,7 @@ class GbxDevice:
|
|||
|
||||
# Prepare some stuff
|
||||
command = None
|
||||
empty_data_byte = 0xFF
|
||||
empty_data_byte = 0x00
|
||||
extra_size = 0
|
||||
audio_low = False
|
||||
if self.MODE == "DMG":
|
||||
|
|
@ -1818,11 +1816,11 @@ class GbxDevice:
|
|||
self._set_fw_variable("DMG_READ_CS_PULSE", 1)
|
||||
_mbc.EnableMapper()
|
||||
self._set_fw_variable("DMG_READ_CS_PULSE", 0)
|
||||
empty_data_byte = 0x00
|
||||
buffer_len = 0x20
|
||||
elif _mbc.GetName() == "MBC7":
|
||||
buffer_len = save_size
|
||||
elif _mbc.GetName() == "MBC6":
|
||||
empty_data_byte = 0xFF
|
||||
audio_low = True
|
||||
self._set_fw_variable("FLASH_METHOD", 0x04) # FLASH_METHOD_DMG_MBC6
|
||||
self._set_fw_variable("FLASH_WE_PIN", 0x01) # WR
|
||||
|
|
@ -1860,13 +1858,15 @@ class GbxDevice:
|
|||
buffer_len = 0x40
|
||||
else:
|
||||
buffer_len = 0x100
|
||||
elif args["save_type"] in (6, 7): # FLASH
|
||||
elif args["save_type"] in (4, 5): # FLASH
|
||||
empty_data_byte = 0xFF
|
||||
ret = self.ReadFlashSaveID()
|
||||
if ret is False:
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"Couldn’t detect the save data flash chip.", "abortable":False})
|
||||
return False
|
||||
(buffer_len, agb_flash_chip, _) = ret
|
||||
elif args["save_type"] == 8: # DACS
|
||||
elif args["save_type"] == 6: # DACS
|
||||
empty_data_byte = 0xFF
|
||||
# Read Chip ID
|
||||
ram_banks = 1
|
||||
self._cart_write(0, 0x90)
|
||||
|
|
@ -1906,11 +1906,11 @@ class GbxDevice:
|
|||
[ bytearray([ self.DEVICE_CMD["AGB_CART_READ_EEPROM"], 1]), bytearray([ self.DEVICE_CMD["AGB_CART_WRITE_EEPROM"], 1]) ], # 4K EEPROM
|
||||
[ bytearray([ self.DEVICE_CMD["AGB_CART_READ_EEPROM"], 2]), bytearray([ self.DEVICE_CMD["AGB_CART_WRITE_EEPROM"], 2]) ], # 64K EEPROM
|
||||
[ self.DEVICE_CMD["AGB_CART_READ_SRAM"], self.DEVICE_CMD["AGB_CART_WRITE_SRAM"] ], # 256K SRAM
|
||||
[ self.DEVICE_CMD["AGB_CART_READ_SRAM"], bytearray([ self.DEVICE_CMD["AGB_CART_WRITE_FLASH_DATA"], 2 if agb_flash_chip == 0x1F3D else 1]) ], # 512K FLASH
|
||||
[ self.DEVICE_CMD["AGB_CART_READ_SRAM"], bytearray([ self.DEVICE_CMD["AGB_CART_WRITE_FLASH_DATA"], 1]) ], # 1M FLASH
|
||||
[ False, False ], # 8M DACS
|
||||
[ self.DEVICE_CMD["AGB_CART_READ_SRAM"], self.DEVICE_CMD["AGB_CART_WRITE_SRAM"] ], # 512K SRAM
|
||||
[ self.DEVICE_CMD["AGB_CART_READ_SRAM"], self.DEVICE_CMD["AGB_CART_WRITE_SRAM"] ], # 1M SRAM
|
||||
[ self.DEVICE_CMD["AGB_CART_READ_SRAM"], bytearray([ self.DEVICE_CMD["AGB_CART_WRITE_FLASH_DATA"], 2 if agb_flash_chip == 0x1F3D else 1]) ], # 512K FLASH
|
||||
[ self.DEVICE_CMD["AGB_CART_READ_SRAM"], bytearray([ self.DEVICE_CMD["AGB_CART_WRITE_FLASH_DATA"], 2 if agb_flash_chip == 0x1F3D else 1]) ], # 1M FLASH
|
||||
[ False, False ], # 8M DACS
|
||||
]
|
||||
command = commands[args["save_type"]][args["mode"] - 2]
|
||||
if args["rtc"] is True:
|
||||
|
|
@ -1960,14 +1960,14 @@ class GbxDevice:
|
|||
elif self.MODE == "AGB":
|
||||
start_address = 0
|
||||
bank_size = 0x10000
|
||||
if args["save_type"] == 8: # DACS
|
||||
if args["save_type"] == 6: # DACS
|
||||
bank_size = 0xFC000
|
||||
end_address = 0xFC000
|
||||
else:
|
||||
end_address = min(save_size, bank_size)
|
||||
|
||||
if save_size > bank_size:
|
||||
if args["save_type"] == 7: # FLASH 1M
|
||||
if args["save_type"] == 5: # FLASH 1M
|
||||
dprint("Switching to FLASH bank {:d}".format(bank))
|
||||
cmds = [
|
||||
[ 0x5555, 0xAA ],
|
||||
|
|
@ -1976,14 +1976,13 @@ class GbxDevice:
|
|||
[ 0, bank ]
|
||||
]
|
||||
self._cart_write_flash(cmds)
|
||||
elif args["save_type"] == 5: # SRAM 1M
|
||||
elif args["save_type"] == 8: # SRAM 1M
|
||||
dprint("Switching to SRAM bank {:d}".format(bank))
|
||||
self._cart_write(0x1000000, bank)
|
||||
else:
|
||||
dprint("Unknown bank switching method")
|
||||
time.sleep(0.1)
|
||||
time.sleep(0.05)
|
||||
|
||||
#buffer_offset = bank * bank_size
|
||||
max_length = 64
|
||||
dprint("start_address=0x{:X}, end_address=0x{:X}, buffer_len=0x{:X}, buffer_offset=0x{:X}".format(start_address, end_address, buffer_len, buffer_offset))
|
||||
pos = start_address
|
||||
|
|
@ -1993,6 +1992,7 @@ class GbxDevice:
|
|||
cancel_args.update(self.CANCEL_ARGS)
|
||||
self.CANCEL_ARGS = {}
|
||||
self.SetProgress(cancel_args)
|
||||
if self.CanPowerCycleCart(): self.CartPowerCycle()
|
||||
return
|
||||
|
||||
if args["mode"] == 2: # Backup
|
||||
|
|
@ -2004,7 +2004,7 @@ class GbxDevice:
|
|||
temp = self.ReadRAM_TAMA5()
|
||||
elif self.MODE == "AGB" and args["save_type"] in (1, 2): # EEPROM
|
||||
temp = self.ReadRAM(address=int(pos/8), length=buffer_len, command=command, max_length=max_length)
|
||||
elif self.MODE == "AGB" and args["save_type"] == 8: # DACS
|
||||
elif self.MODE == "AGB" and args["save_type"] == 6: # DACS
|
||||
temp = self.ReadROM(address=0x1F00000+pos, length=buffer_len, skip_init=False, max_length=max_length)
|
||||
else:
|
||||
temp = self.ReadRAM(address=pos, length=buffer_len, command=command, max_length=max_length)
|
||||
|
|
@ -2036,7 +2036,7 @@ class GbxDevice:
|
|||
self.WriteRAM_TAMA5(buffer=buffer[buffer_offset:buffer_offset+buffer_len])
|
||||
elif self.MODE == "AGB" and args["save_type"] in (1, 2): # EEPROM
|
||||
self.WriteRAM(address=int(pos/8), buffer=buffer[buffer_offset:buffer_offset+buffer_len], command=command)
|
||||
elif self.MODE == "AGB" and args["save_type"] in (6, 7): # FLASH
|
||||
elif self.MODE == "AGB" and args["save_type"] in (4, 5): # FLASH
|
||||
sector_address = int(pos / buffer_len)
|
||||
if agb_flash_chip == 0x1F3D: # Atmel AT29LV512
|
||||
self.WriteRAM(address=int(pos/128), buffer=buffer[buffer_offset:buffer_offset+buffer_len], command=command)
|
||||
|
|
@ -2062,8 +2062,9 @@ class GbxDevice:
|
|||
if lives == 0:
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"Accessing the save data flash chip failed. Please make sure you selected the correct save type. If you are using a reproduction cartridge, check if it really is equipped with a flash chip for save data, or if it uses SRAM for save data instead.", "abortable":False})
|
||||
return False
|
||||
self.WriteRAM(address=pos, buffer=buffer[buffer_offset:buffer_offset+buffer_len], command=command)
|
||||
elif self.MODE == "AGB" and args["save_type"] == 8: # DACS
|
||||
if buffer[buffer_offset:buffer_offset+buffer_len] != bytearray([0xFF] * buffer_len):
|
||||
self.WriteRAM(address=pos, buffer=buffer[buffer_offset:buffer_offset+buffer_len], command=command)
|
||||
elif self.MODE == "AGB" and args["save_type"] == 6: # DACS
|
||||
if (pos+0x1F00000) in (0x1F00000, 0x1F10000, 0x1F20000, 0x1F30000, 0x1F40000, 0x1F50000, 0x1F60000, 0x1F70000, 0x1F80000, 0x1F90000, 0x1FA0000, 0x1FB0000, 0x1FC0000, 0x1FD0000, 0x1FE0000, 0x1FF0000, 0x1FF2000, 0x1FF4000, 0x1FF6000, 0x1FF8000, 0x1FFA000):
|
||||
sector_address = pos+0x1F00000
|
||||
dprint("sector_address:", hex(sector_address))
|
||||
|
|
@ -2179,7 +2180,7 @@ class GbxDevice:
|
|||
return True
|
||||
|
||||
def _FlashROM(self, args):
|
||||
self.FAST_READ = True #args["fast_read_mode"]
|
||||
self.FAST_READ = True
|
||||
|
||||
if "buffer" in args:
|
||||
data_import = args["buffer"]
|
||||
|
|
@ -2254,14 +2255,24 @@ class GbxDevice:
|
|||
if cart_type["command_set"] == "GBMEMORY":
|
||||
flashcart = Flashcart_DMG_MMSA(config=cart_type, cart_write_fncptr=self._cart_write, cart_read_fncptr=self.ReadROM, progress_fncptr=self.SetProgress)
|
||||
if "buffer_map" not in args:
|
||||
try:
|
||||
if os.path.exists(os.path.splitext(args["path"])[0] + ".map"):
|
||||
with open(os.path.splitext(args["path"])[0] + ".map", "rb") as file: args["buffer_map"] = file.read()
|
||||
except:
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"The GB Memory Cartridge requires a hidden sector file, but it wasn’t found.\nExpected path: {:s}".format(os.path.splitext(args["path"])[0] + ".map"), "abortable":False})
|
||||
return False
|
||||
#with open(args["path"], "rb") as f: rom_data = bytearray(f.read())
|
||||
#gbmem = GBMemory(None, rom_data, None)
|
||||
#args["buffer_map"] = gbmem.GetMapData()
|
||||
else:
|
||||
temp = data_import
|
||||
if len(temp) == 0: temp = bytearray([0xFF] * 0x180)
|
||||
try:
|
||||
gbmem = GBMemoryMap(rom=temp)
|
||||
args["buffer_map"] = gbmem.GetMapData()
|
||||
except:
|
||||
print("{:s}An error occured while trying to generate the hidden sector data for the NP GB Memory cartridge.{:s}".format(ANSI.RED, ANSI.RESET))
|
||||
|
||||
if args["buffer_map"] is False:
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"The NP GB Memory Cartridge requires extra hidden sector data. As it couldn’t be auto-generated, please provide your own at the following path: {:s}".format(os.path.splitext(args["path"])[0] + ".map"), "abortable":False})
|
||||
return False
|
||||
else:
|
||||
dprint("Generated hidden sector data:", args["buffer_map"])
|
||||
if Util.DEBUG:
|
||||
with open("debug_mmsa_map.bin", "wb") as f: f.write(args["buffer_map"])
|
||||
data_map_import = copy.copy(args["buffer_map"])
|
||||
data_map_import = bytearray(data_map_import)
|
||||
dprint("Hidden sector data loaded")
|
||||
|
|
@ -2305,8 +2316,6 @@ class GbxDevice:
|
|||
args["mbc"] = 0x1B # MBC5+SRAM+BATTERY
|
||||
_mbc = DMG_MBC().GetInstance(args=args, cart_write_fncptr=self._cart_write, cart_read_fncptr=self._cart_read, cart_powercycle_fncptr=self.CartPowerCycle, clk_toggle_fncptr=self._clk_toggle)
|
||||
|
||||
# I need a cart for testing before this has a chance to work ↓
|
||||
#self._set_fw_variable("FLASH_COMMANDS_BANK_1", 1 if flashcart.FlashCommandsOnBank1() else 0)
|
||||
self._set_fw_variable("FLASH_PULSE_RESET", 1 if flashcart.PulseResetAfterWrite() else 0)
|
||||
|
||||
rom_banks = math.ceil(len(data_import) / _mbc.GetROMBankSize())
|
||||
|
|
@ -2433,7 +2442,6 @@ class GbxDevice:
|
|||
(verified, flash_id) = flashcart.VerifyFlashID()
|
||||
if not verified:
|
||||
print("NOTE: This cartridge’s Flash ID ({:s}) doesn’t match the cartridge type selection.".format(' '.join(format(x, '02X') for x in flash_id)))
|
||||
#return False
|
||||
# ↑↑↑ Read Flash ID
|
||||
|
||||
# ↓↓↓ Read Sector Map
|
||||
|
|
@ -2456,15 +2464,12 @@ class GbxDevice:
|
|||
# ↓↓↓ Chip erase
|
||||
chip_erase = False
|
||||
if flashcart.SupportsChipErase():
|
||||
if flashcart.SupportsSectorErase() and args["prefer_chip_erase"] is False and flashcart.GetSectorMap() is not False:
|
||||
if flashcart.SupportsSectorErase() and args["prefer_chip_erase"] is False and sector_map is not False:
|
||||
chip_erase = False
|
||||
else:
|
||||
chip_erase = True
|
||||
#if flashcart.FlashCommandsOnBank1():
|
||||
# _mbc.SelectBankROM(1)
|
||||
if flashcart.ChipErase() is False:
|
||||
return False
|
||||
#_mbc.SelectBankROM(0)
|
||||
elif flashcart.SupportsSectorErase() is False:
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"No erase method available.", "abortable":False})
|
||||
return False
|
||||
|
|
@ -2524,7 +2529,8 @@ class GbxDevice:
|
|||
cancel_args.update(self.CANCEL_ARGS)
|
||||
self.CANCEL_ARGS = {}
|
||||
self.SetProgress(cancel_args)
|
||||
return False
|
||||
if self.CanPowerCycleCart(): self.CartPowerCycle()
|
||||
return
|
||||
|
||||
if buffer_pos >= len(data_import): break
|
||||
|
||||
|
|
@ -2554,7 +2560,12 @@ class GbxDevice:
|
|||
else:
|
||||
status = self.WriteROM(address=pos, buffer=data_import[buffer_pos:buffer_pos+buffer_len], flash_buffer_size=flash_buffer_size, skip_init=(skip_init and not self.SKIPPING), rumble_stop=rumble)
|
||||
if status is False:
|
||||
self.CANCEL_ARGS = {"info_type":"msgbox_critical", "info_msg":"An error occured while writing 0x{:X} bytes to the flash cartridge at position 0x{:X}. Please make sure that the cartridge contacts are clean, re-connect the device and try again from the beginning.".format(buffer_len, buffer_pos)}
|
||||
if "iteration" in self.ERROR_ARGS and self.ERROR_ARGS["iteration"] > 0:
|
||||
self.CANCEL_ARGS.update({"info_type":"msgbox_critical", "info_msg":"Unstable connection detected while writing 0x{:X} bytes in iteration {:d} at position 0x{:X} ({:s}).\n\nPlease clean the cartridge contacts very thoroughly, then re-connect the device and try again.".format(buffer_len, self.ERROR_ARGS["iteration"], buffer_pos, Util.formatFileSize(size=buffer_pos, asInt=False))})
|
||||
elif buffer_pos > 0:
|
||||
self.CANCEL_ARGS.update({"info_type":"msgbox_critical", "info_msg":"An error occured while writing 0x{:X} bytes at position 0x{:X}.\n\nPlease ensure that your cartridge supports ROMs larger than {:s} and that the cartridge contacts are clean, then re-connect the device and try again.".format(buffer_len, buffer_pos, Util.formatFileSize(size=buffer_pos, asInt=False))})
|
||||
else:
|
||||
self.CANCEL_ARGS.update({"info_type":"msgbox_critical", "info_msg":"An error occured while writing 0x{:X} bytes at position 0x{:X} ({:s}).\n\nPlease make sure that the correct cart type was selected and that the cartridge contacts are clean, then re-connect the device and try again from the beginning.".format(buffer_len, buffer_pos, Util.formatFileSize(size=buffer_pos, asInt=True))})
|
||||
self.CANCEL = True
|
||||
self.ERROR = True
|
||||
continue
|
||||
|
|
@ -2562,9 +2573,8 @@ class GbxDevice:
|
|||
skip_init = True
|
||||
|
||||
buffer_pos += buffer_len
|
||||
self.SetProgress({"action":"UPDATE_POS", "pos":buffer_pos})
|
||||
|
||||
pos += buffer_len
|
||||
self.SetProgress({"action":"UPDATE_POS", "pos":buffer_pos})
|
||||
|
||||
# Hidden Sector
|
||||
if command_set_type == "GBMEMORY":
|
||||
|
|
@ -2586,10 +2596,6 @@ class GbxDevice:
|
|||
self.SetProgress({"action":"INITIALIZE", "method":"ROM_WRITE_VERIFY", "size":buffer_pos})
|
||||
|
||||
verify_args = copy.copy(args)
|
||||
#if self.MODE == "DMG":
|
||||
# rom_banks = math.ceil(len(data_import)/_mbc.GetROMBankSize())
|
||||
#else:
|
||||
# rom_banks = 1
|
||||
|
||||
start_address = 0
|
||||
end_address = buffer_pos
|
||||
|
|
@ -2599,9 +2605,8 @@ class GbxDevice:
|
|||
verified_size = self._BackupROM(verify_args)
|
||||
if self.CANCEL is True:
|
||||
pass
|
||||
#elif (verified_size is not True) and (buffer_pos != verified_size):
|
||||
elif (verified_size is not True) and (len(data_import) != verified_size):
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"The ROM was written completely, but verification of written data failed at address 0x{:X}.".format(verified_size), "abortable":False})
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"The ROM was written completely, but verification of written data failed at address 0x{:X}.\n\nPlease make sure that the correct cart type was selected, that your cartridge actually does support ROMs that are {:s} in size and that the cartridge contacts are clean, then re-connect the device and try again from the beginning.".format(verified_size, Util.formatFileSize(len(data_import))), "abortable":False})
|
||||
return False
|
||||
else:
|
||||
verified = True
|
||||
|
|
|
|||
|
|
@ -119,7 +119,7 @@ class GbxDevice:
|
|||
"AUDIO_HIGH":'8',
|
||||
"AUDIO_LOW":'9',
|
||||
}
|
||||
PCB_VERSIONS = {1:'v1.0', 2:'v1.1', 4:'v1.3', 90:'XMAS', 100:'Mini v1.0', 101:'Mini v1.0d'}
|
||||
PCB_VERSIONS = {1:'v1.0', 2:'v1.1/v1.2', 4:'v1.3', 90:'XMAS', 100:'Mini v1.0', 101:'Mini v1.0d'}
|
||||
SUPPORTED_CARTS = {}
|
||||
|
||||
FW = []
|
||||
|
|
@ -212,11 +212,11 @@ class GbxDevice:
|
|||
self.DEVICE = None
|
||||
continue
|
||||
|
||||
if (self.FW[1] not in (4, 5)):
|
||||
conn_msg.append([0, "NOTE: This version of FlashGBX was developed to be used with GBxCart RW v1.3 and v1.4. Other revisions are untested and may not be fully compatible."])
|
||||
elif self.FW[1] == 4:
|
||||
conn_msg.append([0, "NOTE: FlashGBX is now optimized for the custom high compatibility firmware by Lesserkuma. You can install it in GUI mode from the Tools menu."])
|
||||
conn_msg.append([0, "For help please visit the insideGadgets Discord: https://gbxcart.com/discord"])
|
||||
if (self.FW[1] not in (4, 5)):
|
||||
conn_msg.append([0, "\nNow running in Legacy Mode.\nThis version of FlashGBX was developed to be used with GBxCart RW v1.3 and v1.4.\nOther revisions are untested and may not be fully compatible.\n"])
|
||||
elif self.FW[1] == 4:
|
||||
conn_msg.append([0, "{:s}Now running in Legacy Mode. You can install the optimized firmware version L1 in GUI mode from the “Tools” menu.{:s}".format(ANSI.YELLOW, ANSI.RESET)])
|
||||
|
||||
self.PORT = ports[i]
|
||||
self.DEVICE.timeout = 1
|
||||
|
|
@ -1120,7 +1120,7 @@ class GbxDevice:
|
|||
return False
|
||||
return True
|
||||
|
||||
def ReadInfo(self, setPinsAsInputs=False):
|
||||
def ReadInfo(self, setPinsAsInputs=False, checkRtc=False):
|
||||
if not self.IsConnected(): raise Exception("Couldn’t access the the device.")
|
||||
data = {}
|
||||
self.POS = 0
|
||||
|
|
@ -1244,7 +1244,7 @@ class GbxDevice:
|
|||
# Firmware check R26+
|
||||
# Firmware check CFW
|
||||
if ("agb_rom_size" in args and args["agb_rom_size"] > 32 * 1024 * 1024) or (self.MODE == "DMG" and "mbc" in args and not self.IsSupportedMbc(args["mbc"])) or (self.MODE == "AGB" and "dacs_8m" in self.INFO and self.INFO["dacs_8m"] is True): # 3D Memory
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge is currently not supported by {:s} using the current firmware version of the {:s} device. Please update to the custom high compatibility firmware by Lesserkuma and try again.".format(APPNAME, self.GetFullName()), "abortable":False})
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge is currently not supported by {:s} using the current firmware version of the {:s} device. Please update to the high compatibility firmware and try again.".format(APPNAME, self.GetFullName()), "abortable":False})
|
||||
return False
|
||||
# Firmware check CFW
|
||||
|
||||
|
|
@ -1539,19 +1539,19 @@ class GbxDevice:
|
|||
save_size = 32 * 1024
|
||||
read_command = 'GBA_READ_SRAM'
|
||||
write_command = 'GBA_WRITE_SRAM'
|
||||
elif save_type == 4: # SRAM 64 KB
|
||||
elif save_type == 7: # SRAM 64 KB
|
||||
save_size = 64 * 1024
|
||||
read_command = 'GBA_READ_SRAM'
|
||||
write_command = 'GBA_WRITE_SRAM'
|
||||
elif save_type == 5: # SRAM 128 KB
|
||||
elif save_type == 8: # SRAM 128 KB
|
||||
save_size = 128 * 1024
|
||||
read_command = 'GBA_READ_SRAM'
|
||||
write_command = 'GBA_WRITE_SRAM'
|
||||
bank_count = 2
|
||||
elif save_type == 6: # FLASH 64 KB
|
||||
elif save_type == 4: # FLASH 64 KB
|
||||
save_size = 64 * 1024
|
||||
read_command = 'GBA_READ_SRAM'
|
||||
elif save_type == 7: # FLASH 128 KB
|
||||
elif save_type == 5: # FLASH 128 KB
|
||||
save_size = 128 * 1024
|
||||
read_command = 'GBA_READ_SRAM'
|
||||
bank_count = 2
|
||||
|
|
@ -1560,7 +1560,7 @@ class GbxDevice:
|
|||
|
||||
# Get Save Flash Manufacturer
|
||||
maker_id = None
|
||||
if save_type == 6 or save_type == 7:
|
||||
if save_type == 4 or save_type == 5:
|
||||
maker_id = self.ReadFlashSaveMakerID()
|
||||
if maker_id == "ATMEL" and mode == 3:
|
||||
transfer_size = 128
|
||||
|
|
@ -1611,9 +1611,9 @@ class GbxDevice:
|
|||
if endAddr > (startAddr + save_size): endAddr = startAddr + save_size
|
||||
if save_type == 1 or save_type == 2: # EEPROM
|
||||
self.set_number(eeprom_size, self.DEVICE_CMD["GBA_SET_EEPROM_SIZE"])
|
||||
elif save_type == 5: # 1M SRAM
|
||||
elif save_type == 8: # 1M SRAM
|
||||
self.gbx_flash_write_address_byte(0x1000000, bank)
|
||||
elif (save_type == 6 or save_type == 7) and bank > 0: # FLASH
|
||||
elif (save_type == 4 or save_type == 5) and bank > 0: # FLASH
|
||||
self.set_number(bank, self.DEVICE_CMD["GBA_FLASH_SET_BANK"])
|
||||
|
||||
self.set_number(startAddr, self.DEVICE_CMD["SET_START_ADDRESS"])
|
||||
|
|
@ -1668,7 +1668,7 @@ class GbxDevice:
|
|||
self.wait_for_ack()
|
||||
|
||||
elif self.MODE == "AGB":
|
||||
if save_type == 6 or save_type == 7: # FLASH
|
||||
if save_type == 4 or save_type == 5: # FLASH
|
||||
if maker_id == "ATMEL":
|
||||
self.gbx_flash_write_data_bytes(self.DEVICE_CMD["GBA_FLASH_WRITE_ATMEL"], data)
|
||||
self.wait_for_ack()
|
||||
|
|
@ -1809,9 +1809,9 @@ class GbxDevice:
|
|||
|
||||
elif self.MODE == "AGB":
|
||||
if bank > 0:
|
||||
if (save_type == 5) and bank > 0: # 1M SRAM
|
||||
if (save_type == 8) and bank > 0: # 1M SRAM
|
||||
self.gbx_flash_write_address_byte(0x1000000, 0)
|
||||
elif (save_type == 6 or save_type == 7) and bank > 0: # FLASH
|
||||
elif (save_type == 4 or save_type == 5) and bank > 0: # FLASH
|
||||
self.set_number(0, self.DEVICE_CMD["GBA_FLASH_SET_BANK"])
|
||||
|
||||
if mode == 2:
|
||||
|
|
@ -1918,20 +1918,20 @@ class GbxDevice:
|
|||
# Firmware check R23+
|
||||
# Firmware check R25+
|
||||
if self.MODE == "AGB" and "single_write" in flashcart_meta["commands"] and flashcart_meta["commands"]["single_write"] == [['PA', 0x70], ['PA', 0x10], ['PA', 'PD']] and (([ 0xB0, 0x00, 0xE2, 0x00 ] in flashcart_meta["flash_ids"]) or ([ 0xB0, 0x00, 0xB0, 0x00 ] in flashcart_meta["flash_ids"])): # Dev
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge is currently not supported by {:s} using the current firmware version of the {:s} device. Please check for firmware updates in the Tools menu or the maker’s website.".format(APPNAME, self.GetFullName()), "abortable":False})
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge is currently not supported by {:s} using the current firmware version of the {:s} device. Please check for firmware updates in the “Tools” menu or the maker’s website.".format(APPNAME, self.GetFullName()), "abortable":False})
|
||||
return False
|
||||
# Firmware check R25+
|
||||
# Firmware check R28+
|
||||
if (int(self.FW[0]) >= 28) and self.MODE == "AGB" and ("flash_ids" in flashcart_meta and ([ 0x89, 0x00, 0x89, 0x00, 0x18, 0x00, 0x18, 0x00 ] in flashcart_meta["flash_ids"])): # Flash2Advance
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge is currently not supported by {:s} using the current firmware version of the {:s} device. Please check for firmware updates in the Tools menu or the maker’s website.".format(APPNAME, self.GetFullName()), "abortable":False})
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge is currently not supported by {:s} using the current firmware version of the {:s} device. Please check for firmware updates in the “Tools” menu or the maker’s website.".format(APPNAME, self.GetFullName()), "abortable":False})
|
||||
return False
|
||||
# Firmware check R25+
|
||||
# Firmware check
|
||||
if self.MODE == "AGB" and "buffer_write" in flashcart_meta["commands"] and flashcart_meta["commands"]["buffer_write"] == [['SA', 0xEA], ['SA', 'BS'], ['PA', 'PD'], ['SA', 0xD0], ['SA', 0xFF]]:
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge is currently not supported by {:s} using the current firmware version of the {:s} device. Please check for firmware updates in the Tools menu or the maker’s website.".format(APPNAME, self.GetFullName()), "abortable":False})
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge is currently not supported by {:s} using the current firmware version of the {:s} device. Please check for firmware updates in the “Tools” menu or the maker’s website.".format(APPNAME, self.GetFullName()), "abortable":False})
|
||||
return False
|
||||
if self.MODE == "AGB" and "buffer_size" in flashcart_meta and flashcart_meta["buffer_size"] > 256:
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge is currently not supported by {:s} using the current firmware version of the {:s} device. Please check for firmware updates in the Tools menu or the maker’s website.".format(APPNAME, self.GetFullName()), "abortable":False})
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge is currently not supported by {:s} using the current firmware version of the {:s} device. Please check for firmware updates in the “Tools” menu or the maker’s website.".format(APPNAME, self.GetFullName()), "abortable":False})
|
||||
return False
|
||||
if self.MODE == "DMG" and "single_write" in flashcart_meta["commands"] and "buffer_write" in flashcart_meta["commands"] and flashcart_meta["commands"]["buffer_write"] != [['SA', 0xE8], ['SA', 'BS'], ['PA', 'PD'], ['SA', 0xD0], ['SA', 0xFF]]:
|
||||
print("NOTE: Update your GBxCart RW firmware to version L1 or higher for a better transfer rate with this cartridge.")
|
||||
|
|
@ -1941,7 +1941,7 @@ class GbxDevice:
|
|||
del flashcart_meta["commands"]["buffer_write"]
|
||||
|
||||
#if "dmg-mmsa-jpn" in flashcart_meta:
|
||||
# self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"Flashing GB Memory cartridges is currently only supported via the high compatibility firmware which you can install from the Tools menu.", "abortable":False})
|
||||
# self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"Flashing GB Memory cartridges is currently only supported via the high compatibility firmware which you can install from the “Tools” menu.", "abortable":False})
|
||||
# return False
|
||||
# Firmware check
|
||||
#dprint(flashcart_meta)
|
||||
|
|
@ -2024,7 +2024,7 @@ class GbxDevice:
|
|||
|
||||
# Check if write command exists and quit if not
|
||||
if "single_write" not in flashcart_meta["commands"] and "buffer_write" not in flashcart_meta["commands"]:
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge type is currently not supported for ROM flashing, however you can try the high compatibility firmware which is available through the firmware updater in the Tools menu.", "abortable":False})
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge type is currently not supported for ROM writing using the current firmware version. However, it may be supported via the high compatibility firmware which is available in GUI mode from the “Tools” menu.", "abortable":False})
|
||||
return False
|
||||
|
||||
# Chip Erase
|
||||
|
|
@ -2252,7 +2252,7 @@ class GbxDevice:
|
|||
pos += 32
|
||||
|
||||
else:
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"Buffer writing for this flash chip is not supported with your device’s firmware version. You can try the high compatibility firmware which is available through the firmware updater in the Tools menu.\n\n{:s}".format(str(flashcart_meta["commands"]["buffer_write"])), "abortable":False})
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"Buffer writing for this flash chip is not supported with your device’s firmware version. You can try the high compatibility firmware which is available through the firmware updater in the “Tools” menu.\n\n{:s}".format(str(flashcart_meta["commands"]["buffer_write"])), "abortable":False})
|
||||
return False
|
||||
|
||||
elif self.MODE == "AGB":
|
||||
|
|
@ -2359,7 +2359,7 @@ class GbxDevice:
|
|||
pos += 256
|
||||
|
||||
else:
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"Buffer writing for this flash chip is not supported with your device’s firmware version. You can try the high compatibility firmware which is available through the firmware updater in the Tools menu.\n\n{:s}".format(str(flashcart_meta["commands"]["buffer_write"])), "abortable":False})
|
||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"Buffer writing for this flash chip is not supported with your device’s firmware version. You can try the high compatibility firmware which is available through the firmware updater in the “Tools” menu.\n\n{:s}".format(str(flashcart_meta["commands"]["buffer_write"])), "abortable":False})
|
||||
return False
|
||||
|
||||
elif "single_write" in flashcart_meta["commands"]:
|
||||
|
|
|
|||
Binary file not shown.
12
README.md
12
README.md
|
|
@ -83,11 +83,14 @@ Use this command in a Terminal or Command Prompt window to launch the installed
|
|||
|
||||
- 29LV Series Flash BOY with 29LV160DB
|
||||
- BUNG Doctor GB Card 64M
|
||||
- DIY cart with AM29F010
|
||||
- DIY cart with AM29F016
|
||||
- DIY cart with AM29F032
|
||||
- DIY cart with AM29F040
|
||||
- DIY cart with AM29F080
|
||||
- DIY cart with AT49F040
|
||||
- DIY cart with MBC1 and AM29F080
|
||||
- DIY cart with MBC3 and MX29LV640
|
||||
- DIY cart with MX29LV640
|
||||
- DIY cart with SST39SF040
|
||||
- DMG-MBC5-32M-FLASH Development Cartridge, E201264
|
||||
- Ferrante Crafts cart with SST39SF010A
|
||||
- GB-CART32K-A with SST39SF020A
|
||||
|
|
@ -196,6 +199,7 @@ Use this command in a Terminal or Command Prompt window to launch the installed
|
|||
- AGB-E05-01 with GL128S
|
||||
- AGB-E05-01 with MSP55LV128M
|
||||
- AGB-E05-01 with MX29GL128FHT2I-90G
|
||||
- AGB-E05-01 with S29GL064
|
||||
- AGB-E05-02 with JS28F128
|
||||
- AGB-E05-02 with M29W128FH
|
||||
- AGB-E05-02 with M29W128GH
|
||||
|
|
@ -204,8 +208,10 @@ Use this command in a Terminal or Command Prompt window to launch the installed
|
|||
- AGB-E20-30 with M29W128GH
|
||||
- AGB-E20-30 with S29GL256N10TFI01
|
||||
- AGB-SD-E05 with MSP55LV128
|
||||
- B100 with MX29LV640ET
|
||||
- B104 with MSP55LV128
|
||||
- B11 with 26L6420MC-90
|
||||
- B54 with MX29LV320ET
|
||||
- BX2006_0106_NEW with S29GL128N10TFI01
|
||||
- BX2006_TSOP_64BALL with GL128S
|
||||
- BX2006_TSOP_64BALL with GL256S
|
||||
|
|
@ -263,6 +269,7 @@ The author would like to thank the following very kind people for their help and
|
|||
- dyf2007 (flash chip info)
|
||||
- easthighNerd (feature suggestions)
|
||||
- EchelonPrime (flash chip info)
|
||||
- EmperorOfTigers (bug reports)
|
||||
- endrift (research, mGBA emulator)
|
||||
- eveningmoose (flash chip info)
|
||||
- frarees (bug reports)
|
||||
|
|
@ -276,6 +283,7 @@ The author would like to thank the following very kind people for their help and
|
|||
- Jayro (flash chip info)
|
||||
- JFox (help with properly packaging the app for pip, Linux help)
|
||||
- joyrider3774 (flash chip info)
|
||||
- JS7457 (flash chip info)
|
||||
- julgr (macOS help, testing)
|
||||
- litlemoran (flash chip info)
|
||||
- LovelyA72 (flash chip info)
|
||||
|
|
|
|||
2
setup.py
2
setup.py
|
|
@ -4,7 +4,7 @@ with open("README.md", "r", encoding="utf-8") as fh: long_description = fh.read(
|
|||
|
||||
setuptools.setup(
|
||||
name="FlashGBX",
|
||||
version="3.6",
|
||||
version="3.7",
|
||||
author="Lesserkuma",
|
||||
description="Reads and writes Game Boy and Game Boy Advance cartridge data. Supported hardware: GBxCart RW v1.3 and v1.4 by insideGadgets.",
|
||||
url="https://github.com/lesserkuma/FlashGBX",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user