mirror of
https://github.com/lesserkuma/FlashGBX.git
synced 2026-04-26 10:30:17 -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
|
# 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)
|
### 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
|
- 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)*
|
- 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)*
|
- 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)*
|
- 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)*
|
- 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)
|
- 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 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)*
|
- 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
|
- 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)
|
### 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-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 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)
|
- 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)
|
### v2.3 (released 2021-06-08)
|
||||||
- Added support for AGB-E05-06L with 29LV128DBT2C-90Q *(thanks marv17)*
|
- 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)*
|
- Confirmed support for SD007_TSOP_48BALL_V10 with GL032M10BFIR3 *(thanks Mr_V)*
|
||||||
- Added support for 2006_TSOP_64BALL_6106 with W29GL128SH9B *(thanks marv17)*
|
- Added support for 2006_TSOP_64BALL_6106 with W29GL128SH9B *(thanks marv17)*
|
||||||
- Fixed support for insideGadgets 1 MB, 128 KB SRAM *(thanks AlexiG)*
|
- 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)*
|
- 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)*
|
- 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 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)
|
### v2.1 (released 2021-05-05)
|
||||||
- Fixed support for SD007_TSOP_29LV017D with L017D70VC *(thanks marv17 and 90sFlav)*
|
- 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 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)*
|
- 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
|
- 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
|
- Fixed minor bugs
|
||||||
|
|
||||||
### v1.4.1 (released 2021-03-15)
|
### 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 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 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)
|
- 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”
|
- Renamed config.ini to settings.ini to avoid confusion with the term “config file”
|
||||||
|
|
||||||
### v0.8β (released 2020-10-03)
|
### 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`
|
- 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
|
- 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)*
|
- 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-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("--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-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("--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("--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")
|
#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]
|
dev = self.DEVICE[1]
|
||||||
builddate = dev.GetFWBuildDate()
|
builddate = dev.GetFWBuildDate()
|
||||||
if builddate != "":
|
if builddate != "":
|
||||||
print("\nConnected to {:s} (dated {:s})".format(dev.GetFullNameExtended(), builddate))
|
print("\nConnected to {:s}".format(dev.GetFullNameExtended(more=True)))
|
||||||
else:
|
else:
|
||||||
print("\nConnected to {:s}".format(dev.GetFullNameExtended()))
|
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"]):
|
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))
|
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()
|
cart_types = self.CONN.GetSupportedCartridgesDMG()
|
||||||
for i in range(0, len(cart_types[0])):
|
for i in range(0, len(cart_types[0])):
|
||||||
if "DMG-MMSA-JPN" in cart_types[0][i]:
|
if "DMG-MMSA-JPN" in cart_types[0][i]:
|
||||||
|
|
@ -577,8 +577,8 @@ class FlashGBX_CLI():
|
||||||
data["save_type"] = db_agb_entry['st']
|
data["save_type"] = db_agb_entry['st']
|
||||||
if data["dacs_8m"] is True:
|
if data["dacs_8m"] is True:
|
||||||
stok = True
|
stok = True
|
||||||
s += "Save Type: {:s}\n".format(Util.AGB_Header_Save_Types[8])
|
s += "Save Type: {:s}\n".format(Util.AGB_Header_Save_Types[6])
|
||||||
data["save_type"] = 8
|
data["save_type"] = 6
|
||||||
|
|
||||||
if stok is False:
|
if stok is False:
|
||||||
s += "Save Type: Not detected\n"
|
s += "Save Type: Not detected\n"
|
||||||
|
|
@ -620,7 +620,6 @@ class FlashGBX_CLI():
|
||||||
|
|
||||||
if len(cart_types) > 0:
|
if len(cart_types) > 0:
|
||||||
cart_type = cart_type_id
|
cart_type = cart_type_id
|
||||||
#self.STATUS["cart_type"] = supp_cart_types[1][cart_type]
|
|
||||||
for i in range(0, len(cart_types)):
|
for i in range(0, len(cart_types)):
|
||||||
if cart_types[i] == cart_type_id:
|
if cart_types[i] == cart_type_id:
|
||||||
msg_cart_type += "- {:s}*\n".format(supp_cart_types[0][cart_types[i]])
|
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 / 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/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 ("[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"
|
msg_cart_type_s += "\n"
|
||||||
else:
|
else:
|
||||||
msg_cart_type_s = "Cartridge Type: Generic ROM Cartridge (not rewritable or not auto-detectable)\n"
|
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):
|
def BackupROM(self, args, header):
|
||||||
mbc = 1
|
mbc = 1
|
||||||
rom_size = 0
|
rom_size = 0
|
||||||
#fast_read_mode = args.fast_read_mode is True
|
|
||||||
|
|
||||||
if self.CONN.GetMode() == "DMG":
|
if self.CONN.GetMode() == "DMG":
|
||||||
if args.dmg_mbc == "auto":
|
if args.dmg_mbc == "auto":
|
||||||
|
|
@ -711,11 +711,9 @@ class FlashGBX_CLI():
|
||||||
|
|
||||||
if args.dmg_romsize == "auto":
|
if args.dmg_romsize == "auto":
|
||||||
try:
|
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"]]
|
rom_size = Util.DMG_Header_ROM_Sizes_Flasher_Map[header["rom_size_raw"]]
|
||||||
except:
|
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))
|
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
|
rom_size = 8 * 1024 * 1024
|
||||||
else:
|
else:
|
||||||
sizes = [ "auto", "32kb", "64kb", "128kb", "256kb", "512kb", "1mb", "2mb", "4mb", "8mb", "16mb", "32mb" ]
|
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))
|
print("{:s}Couldn’t access “{:s}”.{:s}".format(ANSI.RED, path, ANSI.RESET))
|
||||||
return
|
return
|
||||||
|
|
||||||
#if fast_read_mode: print("Fast Read Mode enabled.")
|
|
||||||
s_mbc = ""
|
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":
|
if self.CONN.GetMode() == "DMG":
|
||||||
print("The ROM will now be read{:s} and saved to “{:s}”.".format(s_mbc, os.path.abspath(path)))
|
print("The ROM will now be read{:s} and saved to “{:s}”.".format(s_mbc, os.path.abspath(path)))
|
||||||
else:
|
else:
|
||||||
|
|
@ -788,7 +789,6 @@ class FlashGBX_CLI():
|
||||||
if carts[i]["type"] != self.CONN.GetMode(): continue
|
if carts[i]["type"] != self.CONN.GetMode(): continue
|
||||||
if args.flashcart_type in carts[i]["names"]:
|
if args.flashcart_type in carts[i]["names"]:
|
||||||
print("Selected flash cartridge type: {:s}".format(args.flashcart_type))
|
print("Selected flash cartridge type: {:s}".format(args.flashcart_type))
|
||||||
#rom_banks = int(carts[i]["flash_size"] / 0x4000)
|
|
||||||
rom_size = carts[i]["flash_size"]
|
rom_size = carts[i]["flash_size"]
|
||||||
cart_type = i
|
cart_type = i
|
||||||
break
|
break
|
||||||
|
|
@ -815,7 +815,6 @@ class FlashGBX_CLI():
|
||||||
break
|
break
|
||||||
|
|
||||||
if cart_type <= 0 and args.flashcart_type == "autodetect":
|
if cart_type <= 0 and args.flashcart_type == "autodetect":
|
||||||
#cart_type = self.DetectCartridge(limitVoltage=not args.force_5v)
|
|
||||||
cart_type = self.DetectCartridge()
|
cart_type = self.DetectCartridge()
|
||||||
if cart_type is None: cart_type = 0
|
if cart_type is None: cart_type = 0
|
||||||
if 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']:
|
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.")
|
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
|
verify_write = args.no_verify_write is False
|
||||||
|
|
||||||
fix_header = False
|
fix_header = False
|
||||||
|
|
@ -898,7 +896,6 @@ class FlashGBX_CLI():
|
||||||
return
|
return
|
||||||
|
|
||||||
print("")
|
print("")
|
||||||
#if fast_read_mode: print("Fast Read Mode enabled for flash verification.")
|
|
||||||
v = carts[cart_type]["voltage"]
|
v = carts[cart_type]["voltage"]
|
||||||
if override_voltage: v = override_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)))
|
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":
|
if args.agb_savetype == "auto":
|
||||||
save_type = header["save_type"]
|
save_type = header["save_type"]
|
||||||
else:
|
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)
|
save_type = sizes.index(args.agb_savetype)
|
||||||
|
|
||||||
path = header["game_title"].strip().encode('ascii', 'ignore').decode('ascii')
|
path = header["game_title"].strip().encode('ascii', 'ignore').decode('ascii')
|
||||||
|
|
@ -987,7 +984,11 @@ class FlashGBX_CLI():
|
||||||
if (path == ""): return
|
if (path == ""): return
|
||||||
|
|
||||||
s_mbc = ""
|
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 args.action == "backup-save":
|
||||||
if not args.overwrite and os.path.exists(os.path.abspath(path)):
|
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()
|
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)
|
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
|
elif args.action == "debug-test-save": # debug
|
||||||
self.ARGS["debug"] = True
|
self.ARGS["debug"] = True
|
||||||
#self.CONN.DetectCartridge()
|
|
||||||
#return
|
|
||||||
|
|
||||||
print("Making a backup of the original save data.")
|
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)
|
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)
|
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)
|
time.sleep(0.1)
|
||||||
with open(self.CONFIG_PATH + "/test3.bin", "rb") as f: test3 = bytearray(f.read())
|
with open(self.CONFIG_PATH + "/test3.bin", "rb") as f: test3 = bytearray(f.read())
|
||||||
print("\nPower cycling.")
|
if self.CONN.CanPowerCycleCart():
|
||||||
self.CONN.CartPowerOff()
|
print("\nPower cycling.")
|
||||||
time.sleep(1)
|
self.CONN.CartPowerOff()
|
||||||
self.CONN.CartPowerOn()
|
time.sleep(1)
|
||||||
|
self.CONN.CartPowerOn()
|
||||||
|
self.CONN.ReadInfo(checkRtc=False)
|
||||||
time.sleep(0.2)
|
time.sleep(0.2)
|
||||||
print("\nReading back and comparing data again.")
|
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)
|
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)
|
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)
|
time.sleep(0.1)
|
||||||
|
|
||||||
|
if mbc == 6:
|
||||||
|
for i in range(0, len(test2)):
|
||||||
|
test2[i] &= 0x0F
|
||||||
|
test3[i] &= 0x0F
|
||||||
|
|
||||||
if test2 != test4:
|
if test2 != test4:
|
||||||
diffcount = 0
|
diffcount = 0
|
||||||
for i in range(0, len(test2)):
|
for i in range(0, len(test2)):
|
||||||
|
|
@ -1080,11 +1086,6 @@ class FlashGBX_CLI():
|
||||||
if test3[i] != test4[i]: diffcount += 1
|
if test3[i] != test4[i]: diffcount += 1
|
||||||
print("\n{:s}Differences found between two consecutive readbacks: {:d}{:s}".format(ANSI.RED, diffcount, ANSI.RESET))
|
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])
|
found_offset = test2.find(test3[0:512])
|
||||||
if found_offset < 0:
|
if found_offset < 0:
|
||||||
if self.CONN.GetMode() == "AGB":
|
if self.CONN.GetMode() == "AGB":
|
||||||
|
|
@ -1150,9 +1151,8 @@ class FlashGBX_CLI():
|
||||||
self.INI = Util.IniSettings(ini=ini_file, main_section="Firmware")
|
self.INI = Util.IniSettings(ini=ini_file, main_section="Firmware")
|
||||||
fw_ver = self.INI.GetValue("fw_ver")
|
fw_ver = self.INI.GetValue("fw_ver")
|
||||||
fw_buildts = self.INI.GetValue("fw_buildts")
|
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))
|
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:
|
if len(input("").strip()) != 0:
|
||||||
print("Canceled.")
|
print("Canceled.")
|
||||||
|
|
|
||||||
|
|
@ -189,14 +189,11 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
||||||
if platform.system() == "Darwin": btnWidth += 12
|
if platform.system() == "Darwin": btnWidth += 12
|
||||||
self.btnConfig.setMaximumWidth(btnWidth)
|
self.btnConfig.setMaximumWidth(btnWidth)
|
||||||
|
|
||||||
#self.mnuDevice = QtWidgets.QMenu("&Device options")
|
|
||||||
|
|
||||||
self.mnuConfig = QtWidgets.QMenu()
|
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("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("&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("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("&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.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.addSeparator()
|
||||||
self.mnuConfig.addAction("Re-&enable suppressed messages", self.ReEnableMessages)
|
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()[1].setCheckable(True)
|
||||||
self.mnuConfig.actions()[2].setCheckable(True)
|
self.mnuConfig.actions()[2].setCheckable(True)
|
||||||
self.mnuConfig.actions()[3].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()[4].setCheckable(True)
|
||||||
self.mnuConfig.actions()[0].setChecked(self.SETTINGS.value("UpdateCheck") == "enabled")
|
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()[1].setChecked(self.SETTINGS.value("SaveFileNameAddDateTime", default="disabled") == "enabled")
|
||||||
self.mnuConfig.actions()[2].setChecked(self.SETTINGS.value("PreferChipErase", 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()[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.mnuConfig.actions()[4].setChecked(self.SETTINGS.value("AutoDetectLimitVoltage", default="disabled") == "enabled")
|
||||||
|
|
||||||
self.btnConfig.setMenu(self.mnuConfig)
|
self.btnConfig.setMenu(self.mnuConfig)
|
||||||
|
|
@ -280,14 +275,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
||||||
rowHeaderRevision.addWidget(self.lblHeaderRevisionResult)
|
rowHeaderRevision.addWidget(self.lblHeaderRevisionResult)
|
||||||
group_layout.addLayout(rowHeaderRevision)
|
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()
|
rowHeaderRtc = QtWidgets.QHBoxLayout()
|
||||||
lblHeaderRtc = QtWidgets.QLabel("Real Time Clock:")
|
lblHeaderRtc = QtWidgets.QLabel("Real Time Clock:")
|
||||||
lblHeaderRtc.setContentsMargins(0, 1, 0, 1)
|
lblHeaderRtc.setContentsMargins(0, 1, 0, 1)
|
||||||
|
|
@ -393,14 +380,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
||||||
rowAGBHeaderRevision.addWidget(self.lblAGBHeaderRevisionResult)
|
rowAGBHeaderRevision.addWidget(self.lblAGBHeaderRevisionResult)
|
||||||
group_layout.addLayout(rowAGBHeaderRevision)
|
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()
|
rowAGBGpioRtc = QtWidgets.QHBoxLayout()
|
||||||
lblAGBGpioRtc = QtWidgets.QLabel("Real Time Clock:")
|
lblAGBGpioRtc = QtWidgets.QLabel("Real Time Clock:")
|
||||||
lblAGBGpioRtc.setContentsMargins(0, 1, 0, 1)
|
lblAGBGpioRtc.setContentsMargins(0, 1, 0, 1)
|
||||||
|
|
@ -557,7 +536,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
||||||
self.btnRestoreRAM.setEnabled(False)
|
self.btnRestoreRAM.setEnabled(False)
|
||||||
self.btnConnect.setText("&Connect")
|
self.btnConnect.setText("&Connect")
|
||||||
self.lblDevice.setText("Disconnected.")
|
self.lblDevice.setText("Disconnected.")
|
||||||
#self.mnuTools.actions()[2].setEnabled(False)
|
|
||||||
|
|
||||||
def ReEnableMessages(self):
|
def ReEnableMessages(self):
|
||||||
self.SETTINGS.setValue("AutoReconnect", "disabled")
|
self.SETTINGS.setValue("AutoReconnect", "disabled")
|
||||||
|
|
@ -756,13 +734,14 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
||||||
self.btnConnect.setEnabled(True)
|
self.btnConnect.setEnabled(True)
|
||||||
|
|
||||||
if len(self.DEVICES) == 0: return False
|
if len(self.DEVICES) == 0: return False
|
||||||
|
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def AbortOperation(self):
|
def AbortOperation(self):
|
||||||
self.CONN.CANCEL = True
|
self.CONN.CANCEL = True
|
||||||
self.CONN.ERROR = False
|
self.CONN.ERROR = False
|
||||||
|
self.lblStatus4a.setText("Stopping... Please wait.")
|
||||||
|
self.lblStatus4aResult.setText("")
|
||||||
|
|
||||||
def FinishOperation(self):
|
def FinishOperation(self):
|
||||||
if self.lblStatus2aResult.text() == "Pending...": self.lblStatus2aResult.setText("–")
|
if self.lblStatus2aResult.text() == "Pending...": self.lblStatus2aResult.setText("–")
|
||||||
self.lblStatus4aResult.setText("")
|
self.lblStatus4aResult.setText("")
|
||||||
|
|
@ -1013,9 +992,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
||||||
|
|
||||||
def FlashROM(self, dpath=""):
|
def FlashROM(self, dpath=""):
|
||||||
if not self.CheckDeviceAlive(): return
|
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
|
just_erase = False
|
||||||
path = ""
|
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."
|
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)
|
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
|
if answer == QtWidgets.QMessageBox.Cancel: return
|
||||||
|
|
||||||
override_voltage = False
|
override_voltage = False
|
||||||
if 'voltage_variants' in carts[cart_type] and carts[cart_type]['voltage'] == 3.3:
|
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?")
|
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 (safer) ", QtWidgets.QMessageBox.ActionRole)
|
button_3_3v = msgbox.addButton("Use &3.3V", QtWidgets.QMessageBox.ActionRole)
|
||||||
button_5v = msgbox.addButton("Use &5V", QtWidgets.QMessageBox.ActionRole)
|
button_5v = msgbox.addButton("Use &5V", QtWidgets.QMessageBox.ActionRole)
|
||||||
button_cancel = msgbox.addButton("&Cancel", QtWidgets.QMessageBox.RejectRole)
|
button_cancel = msgbox.addButton("&Cancel", QtWidgets.QMessageBox.RejectRole)
|
||||||
msgbox.setDefaultButton(button_3_3v)
|
msgbox.setDefaultButton(button_3_3v)
|
||||||
|
|
@ -1114,12 +1090,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
||||||
else:
|
else:
|
||||||
prefer_chip_erase = False
|
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")
|
verify_write = self.SETTINGS.value("VerifyWrittenData", default="enabled")
|
||||||
if verify_write and verify_write.lower() == "enabled":
|
if verify_write and verify_write.lower() == "enabled":
|
||||||
verify_write = True
|
verify_write = True
|
||||||
|
|
@ -1439,7 +1409,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
||||||
self.btnRestoreRAM.setEnabled(True)
|
self.btnRestoreRAM.setEnabled(True)
|
||||||
self.btnHeaderRefresh.setFocus()
|
self.btnHeaderRefresh.setFocus()
|
||||||
self.SetProgressBars(min=0, max=100, value=0)
|
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.")
|
self.lblStatus4a.setText("Ready.")
|
||||||
qt_app.processEvents()
|
qt_app.processEvents()
|
||||||
|
|
||||||
|
|
@ -1556,7 +1525,7 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
||||||
self.lblHeaderTitleResult.setStyleSheet(self.lblHeaderRevisionResult.styleSheet())
|
self.lblHeaderTitleResult.setStyleSheet(self.lblHeaderRevisionResult.styleSheet())
|
||||||
if data['logo_correct'] and not self.CONN.IsSupportedMbc(data["features_raw"]) and resetStatus:
|
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)
|
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()
|
cart_types = self.CONN.GetSupportedCartridgesDMG()
|
||||||
for i in range(0, len(cart_types[0])):
|
for i in range(0, len(cart_types[0])):
|
||||||
if "dmg-mmsa-jpn" in cart_types[1][i]:
|
if "dmg-mmsa-jpn" in cart_types[1][i]:
|
||||||
|
|
@ -1582,13 +1551,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
||||||
self.lblAGBHeaderLogoValidResult.setText("Invalid")
|
self.lblAGBHeaderLogoValidResult.setText("Invalid")
|
||||||
self.lblAGBHeaderLogoValidResult.setStyleSheet("QLabel { color: red; }")
|
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 data['has_rtc']:
|
||||||
if 'rtc_buffer' in data:
|
if 'rtc_buffer' in data:
|
||||||
try:
|
try:
|
||||||
|
|
@ -1657,7 +1619,7 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
||||||
if db_agb_entry['st'] < len(Util.AGB_Header_Save_Types):
|
if db_agb_entry['st'] < len(Util.AGB_Header_Save_Types):
|
||||||
self.cmbAGBSaveTypeResult.setCurrentIndex(db_agb_entry['st'])
|
self.cmbAGBSaveTypeResult.setCurrentIndex(db_agb_entry['st'])
|
||||||
if data["dacs_8m"] is True:
|
if data["dacs_8m"] is True:
|
||||||
self.cmbAGBSaveTypeResult.setCurrentIndex(8)
|
self.cmbAGBSaveTypeResult.setCurrentIndex(6)
|
||||||
|
|
||||||
if data['empty'] == True: # defaults
|
if data['empty'] == True: # defaults
|
||||||
if data['empty_nocart'] == True:
|
if data['empty_nocart'] == True:
|
||||||
|
|
@ -1704,7 +1666,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
||||||
self.lblStatus4a.setText("Detecting Cartridge...")
|
self.lblStatus4a.setText("Detecting Cartridge...")
|
||||||
self.SetProgressBars(min=0, max=0, value=1)
|
self.SetProgressBars(min=0, max=0, value=1)
|
||||||
qt_app.processEvents()
|
qt_app.processEvents()
|
||||||
#self.ReadCartridge(resetStatus=False)
|
|
||||||
|
|
||||||
limitVoltage = str(self.SETTINGS.value("AutoDetectLimitVoltage", default="disabled")).lower() == "enabled"
|
limitVoltage = str(self.SETTINGS.value("AutoDetectLimitVoltage", default="disabled")).lower() == "enabled"
|
||||||
ret = self.CONN.DetectCartridge(limitVoltage=limitVoltage, checkSaveType=not canSkipMessage)
|
ret = self.CONN.DetectCartridge(limitVoltage=limitVoltage, checkSaveType=not canSkipMessage)
|
||||||
|
|
@ -1733,7 +1694,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
||||||
|
|
||||||
if len(cart_types) > 0:
|
if len(cart_types) > 0:
|
||||||
cart_type = cart_type_id
|
cart_type = cart_type_id
|
||||||
#if (cart_type == 1): cart_type = 0
|
|
||||||
if self.CONN.GetMode() == "DMG":
|
if self.CONN.GetMode() == "DMG":
|
||||||
self.cmbDMGCartridgeTypeResult.setCurrentIndex(cart_type)
|
self.cmbDMGCartridgeTypeResult.setCurrentIndex(cart_type)
|
||||||
elif self.CONN.GetMode() == "AGB":
|
elif self.CONN.GetMode() == "AGB":
|
||||||
|
|
@ -1746,7 +1706,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
||||||
else:
|
else:
|
||||||
msg_cart_type += "- {:s}<br>".format(supp_cart_types[0][cart_types[i]])
|
msg_cart_type += "- {:s}<br>".format(supp_cart_types[0][cart_types[i]])
|
||||||
msg_cart_type = msg_cart_type[:-4]
|
msg_cart_type = msg_cart_type[:-4]
|
||||||
#if msg_cart_type == "": msg_cart_type = "{:s}<br>".format(supp_cart_types[0][0])
|
|
||||||
|
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
@ -1779,11 +1738,10 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
||||||
msg_flash_size_s = ""
|
msg_flash_size_s = ""
|
||||||
msg_flash_id_s = ""
|
msg_flash_id_s = ""
|
||||||
msg_cfi_s = ""
|
msg_cfi_s = ""
|
||||||
|
try_this = None
|
||||||
found_supported = False
|
found_supported = False
|
||||||
is_generic = False
|
is_generic = False
|
||||||
if cart_type is not None:
|
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:
|
if len(cart_types) > 1:
|
||||||
msg_cart_type_s = "<b>Cartridge Type:</b> {:s} (or compatible)<br>".format(msg_cart_type_used)
|
msg_cart_type_s = "<b>Cartridge Type:</b> {:s} (or compatible)<br>".format(msg_cart_type_used)
|
||||||
else:
|
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))
|
msg_flash_size_s = "<b>ROM Size:</b> {:s}<br>".format(Util.formatFileSize(size, asInt=True))
|
||||||
|
|
||||||
else:
|
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)):
|
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."
|
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."
|
if ("[ 0/90]" in flash_id):
|
||||||
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."
|
try_this = "Generic Flash Cartridge (0/90)"
|
||||||
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 ("[ AAA/AA]" in flash_id):
|
||||||
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."
|
try_this = "Generic Flash Cartridge (AAA/AA)"
|
||||||
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 ("[ AAA/A9]" in flash_id):
|
||||||
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."
|
try_this = "Generic Flash Cartridge (AAA/A9)"
|
||||||
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 ("[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>"
|
msg_cart_type_s += "<br>"
|
||||||
else:
|
else:
|
||||||
msg_cart_type_s = "<b>Cartridge Type:</b> Generic ROM Cartridge (not rewritable or not auto-detectable)<br>"
|
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)
|
button_ok = msgbox.addButton("&OK", QtWidgets.QMessageBox.ActionRole)
|
||||||
msgbox.setDefaultButton(button_ok)
|
msgbox.setDefaultButton(button_ok)
|
||||||
msgbox.setEscapeButton(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:
|
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())
|
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)
|
button_clipboard = msgbox.addButton(" &Copy to Clipboard ", QtWidgets.QMessageBox.ActionRole)
|
||||||
else:
|
else:
|
||||||
msg_fw = ""
|
msg_fw = ""
|
||||||
button_clipboard = None
|
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 = "{: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]
|
temp = temp[:-4]
|
||||||
msgbox.setText(temp)
|
msgbox.setText(temp)
|
||||||
|
|
@ -1886,6 +1863,13 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
||||||
doc.setHtml(temp)
|
doc.setHtml(temp)
|
||||||
temp = doc.toPlainText()
|
temp = doc.toPlainText()
|
||||||
clipboard.setText(temp)
|
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.btnHeaderRefresh.setEnabled(True)
|
||||||
self.btnDetectCartridge.setEnabled(True)
|
self.btnDetectCartridge.setEnabled(True)
|
||||||
|
|
|
||||||
|
|
@ -61,12 +61,6 @@ class Flashcart:
|
||||||
def GetMBC(self):
|
def GetMBC(self):
|
||||||
if (self.CONFIG["type"].upper() == "AGB") or ("mbc" not in self.CONFIG): return False
|
if (self.CONFIG["type"].upper() == "AGB") or ("mbc" not in self.CONFIG): return False
|
||||||
mbc = self.CONFIG["mbc"]
|
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
|
return mbc
|
||||||
|
|
||||||
def FlashCommandsOnBank1(self):
|
def FlashCommandsOnBank1(self):
|
||||||
|
|
@ -86,7 +80,6 @@ class Flashcart:
|
||||||
if buffer_size is False:
|
if buffer_size is False:
|
||||||
return False
|
return False
|
||||||
else:
|
else:
|
||||||
#return True
|
|
||||||
return ("buffer_write" in self.CONFIG["commands"])
|
return ("buffer_write" in self.CONFIG["commands"])
|
||||||
|
|
||||||
def SupportsSingleWrite(self):
|
def SupportsSingleWrite(self):
|
||||||
|
|
@ -133,6 +126,9 @@ class Flashcart:
|
||||||
cfi = self.ReadCFI()
|
cfi = self.ReadCFI()
|
||||||
if cfi is False:
|
if cfi is False:
|
||||||
print("CFI ERROR: Couldn’t retrieve buffer size from the cartridge.")
|
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
|
return False
|
||||||
if not "buffer_size" in cfi: return False
|
if not "buffer_size" in cfi: return False
|
||||||
buffer_size = cfi["buffer_size"]
|
buffer_size = cfi["buffer_size"]
|
||||||
|
|
@ -197,11 +193,9 @@ class Flashcart:
|
||||||
self.CONFIG["commands"]["read_cfi"] = [ [ 0xAA, 0x98 ] ]
|
self.CONFIG["commands"]["read_cfi"] = [ [ 0xAA, 0x98 ] ]
|
||||||
|
|
||||||
if "read_cfi" in self.CONFIG["commands"]:
|
if "read_cfi" in self.CONFIG["commands"]:
|
||||||
#print(self.CONFIG["commands"]["read_cfi"])
|
|
||||||
self.CartWrite(self.CONFIG["commands"]["read_cfi"])
|
self.CartWrite(self.CONFIG["commands"]["read_cfi"])
|
||||||
time.sleep(0.1)
|
time.sleep(0.1)
|
||||||
buffer = self.CartRead(0, 0x400)
|
buffer = self.CartRead(0, 0x400)
|
||||||
#print(buffer)
|
|
||||||
self.Reset()
|
self.Reset()
|
||||||
cfi = CFI().Parse(buffer)
|
cfi = CFI().Parse(buffer)
|
||||||
if cfi is not False:
|
if cfi is not False:
|
||||||
|
|
@ -232,6 +226,9 @@ class Flashcart:
|
||||||
cfi = self.ReadCFI()
|
cfi = self.ReadCFI()
|
||||||
if cfi is False:
|
if cfi is False:
|
||||||
print("CFI ERROR: Couldn’t retrieve sector size map from the cartridge.")
|
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
|
return False
|
||||||
sector_size = cfi["erase_sector_blocks"]
|
sector_size = cfi["erase_sector_blocks"]
|
||||||
if cfi["tb_boot_sector_raw"] == 0x03: sector_size.reverse()
|
if cfi["tb_boot_sector_raw"] == 0x03: sector_size.reverse()
|
||||||
|
|
@ -276,8 +273,6 @@ class Flashcart:
|
||||||
|
|
||||||
def SectorErase(self, pos=0, buffer_pos=0):
|
def SectorErase(self, pos=0, buffer_pos=0):
|
||||||
self.Reset(full_reset=False)
|
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_erase" not in self.CONFIG["commands"]: return False
|
||||||
if "sector_size" not in self.CONFIG: return False
|
if "sector_size" not in self.CONFIG: return False
|
||||||
for i in range(0, len(self.CONFIG["commands"]["sector_erase"])):
|
for i in range(0, len(self.CONFIG["commands"]["sector_erase"])):
|
||||||
|
|
@ -330,7 +325,6 @@ class Flashcart:
|
||||||
except:
|
except:
|
||||||
dprint("Warning: Sector map is smaller than expected.")
|
dprint("Warning: Sector map is smaller than expected.")
|
||||||
self.SECTOR_POS -= 1
|
self.SECTOR_POS -= 1
|
||||||
#self.CONFIG["sector_size"][self.SECTOR_POS][0]
|
|
||||||
return sector_size
|
return sector_size
|
||||||
else:
|
else:
|
||||||
return self.CONFIG["sector_size"]
|
return self.CONFIG["sector_size"]
|
||||||
|
|
@ -478,9 +472,6 @@ class CFI:
|
||||||
return info
|
return info
|
||||||
|
|
||||||
class Flashcart_DMG_MMSA(Flashcart):
|
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):
|
def ReadCFI(self):
|
||||||
return False
|
return False
|
||||||
|
|
||||||
|
|
@ -494,7 +485,6 @@ class Flashcart_DMG_MMSA(Flashcart):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def EraseHiddenSector(self, buffer):
|
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})
|
if self.PROGRESS_FNCPTR is not None: self.PROGRESS_FNCPTR({"action":"SECTOR_ERASE", "sector_pos":0, "time_start":time.time(), "abortable":False})
|
||||||
|
|
||||||
self.UnlockForWriting()
|
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):
|
def CalcChecksum(self, buffer):
|
||||||
header = RomFileDMG(buffer[:0x180]).GetHeader()
|
header = RomFileDMG(buffer[:0x180]).GetHeader()
|
||||||
|
target_chk_value = 0
|
||||||
if header["game_title"] == "NP M-MENU MENU":
|
if header["game_title"] == "NP M-MENU MENU":
|
||||||
|
target_sha1_value = "15f5d445c0b2fdf4221cf2a986a4a5cb8dfda131"
|
||||||
target_chk_value = 0x19E8
|
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
|
return 0
|
||||||
elif buffer[0:0x180] == buffer[0x20000:0x20180]:
|
elif buffer[0:0x180] == buffer[0x20000:0x20180]:
|
||||||
return 1
|
return 1
|
||||||
|
|
|
||||||
|
|
@ -33,16 +33,18 @@ class RomFileDMG:
|
||||||
return checksum
|
return checksum
|
||||||
|
|
||||||
def CalcChecksumGlobal(self, fix=False):
|
def CalcChecksumGlobal(self, fix=False):
|
||||||
checksum = 0
|
temp1 = self.ROMFILE[0x14E]
|
||||||
for i in range(0, len(self.ROMFILE), 2):
|
temp2 = self.ROMFILE[0x14F]
|
||||||
if i != 0x14E:
|
self.ROMFILE[0x14E] = 0
|
||||||
checksum = checksum + self.ROMFILE[i + 1]
|
self.ROMFILE[0x14F] = 0
|
||||||
checksum = checksum + self.ROMFILE[i]
|
checksum = sum(self.ROMFILE) & 0xFFFF
|
||||||
|
|
||||||
if fix:
|
if fix:
|
||||||
self.ROMFILE[0x14E] = checksum >> 8
|
self.ROMFILE[0x14E] = checksum >> 8
|
||||||
self.ROMFILE[0x14F] = checksum & 0xFF
|
self.ROMFILE[0x14F] = checksum & 0xFF
|
||||||
return checksum & 0xFFFF
|
else:
|
||||||
|
self.ROMFILE[0x14E] = temp1
|
||||||
|
self.ROMFILE[0x14F] = temp2
|
||||||
|
return checksum
|
||||||
|
|
||||||
def FixHeader(self):
|
def FixHeader(self):
|
||||||
self.CalcChecksumHeader(True)
|
self.CalcChecksumHeader(True)
|
||||||
|
|
@ -78,13 +80,13 @@ class RomFileDMG:
|
||||||
data["features"] = "?"
|
data["features"] = "?"
|
||||||
data["rom_size_raw"] = int(buffer[0x148])
|
data["rom_size_raw"] = int(buffer[0x148])
|
||||||
data["rom_size"] = "?"
|
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])
|
data["ram_size_raw"] = int(buffer[0x149])
|
||||||
if data["features_raw"] == 0x05 or data["features_raw"] == 0x06:
|
if data["features_raw"] == 0x05 or data["features_raw"] == 0x06:
|
||||||
data["ram_size"] = 0x200
|
data["ram_size"] = 0x200
|
||||||
else:
|
else:
|
||||||
data["ram_size"] = "?"
|
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["ram_size"] = Util.DMG_Header_RAM_Sizes[buffer[0x149]]
|
||||||
data["version"] = int(buffer[0x14C])
|
data["version"] = int(buffer[0x14C])
|
||||||
data["header_checksum"] = int(buffer[0x14D])
|
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:
|
if data["features_raw"] == 0x19 and data["game_title"] == "NP M-MENU MENU" and data["header_checksum"] == 0xD3:
|
||||||
data["features_raw"] = 0x105
|
data["features_raw"] = 0x105
|
||||||
data["ram_size_raw"] = 0x04
|
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)
|
# M161 (Mani 4 in 1)
|
||||||
elif data["features_raw"] == 0x10 and data["game_title"] == "TETRIS SET" and data["header_checksum"] == 0x3F:
|
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"] == "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"] == 0x11 and data["game_title"] == "RTYPE 2 SET" and data["header_checksum"] == 0x32:
|
||||||
data["features_raw"] = 0x0B
|
data["features_raw"] = 0x0B
|
||||||
|
|
||||||
# Unlicensed 256M Mapper
|
# 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["features_raw"] = 0x201
|
||||||
data["rom_size_raw"] = 0x0A
|
data["rom_size_raw"] = 0x0A
|
||||||
data["ram_size_raw"] = 0x201
|
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
|
# 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
|
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
|
# Common constants
|
||||||
APPNAME = "FlashGBX"
|
APPNAME = "FlashGBX"
|
||||||
VERSION_PEP440 = "3.6"
|
VERSION_PEP440 = "3.7"
|
||||||
VERSION = "v{:s}".format(VERSION_PEP440)
|
VERSION = "v{:s}".format(VERSION_PEP440)
|
||||||
DEBUG = False
|
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 = [ "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_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_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, 65536, 131072, 1032192 ]
|
AGB_Header_Save_Sizes = [ 0, 512, 8192, 32768, 65536, 131072, 1032192, 65536, 131072 ]
|
||||||
AGB_Global_CRC32 = 0
|
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 = { 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 ]
|
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_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 = [ "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_Map = [ 0x00, 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0A ]
|
||||||
#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_Flasher_Map = [ 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000 ]
|
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 = [ "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 ]
|
DMG_Header_RAM_Sizes_Map = [ 0x00, 0x01, 0x01, 0x02, 0x03, 0x05, 0x04, 0x104, 0x101, 0x102, 0x103, 0x201 ]
|
||||||
|
|
@ -66,7 +65,6 @@ class IniSettings():
|
||||||
path = ""
|
path = ""
|
||||||
|
|
||||||
if path == "":
|
if path == "":
|
||||||
#buf = io.StringIO(ini)
|
|
||||||
self.FILENAME = False
|
self.FILENAME = False
|
||||||
self.SETTINGS = configparser.RawConfigParser()
|
self.SETTINGS = configparser.RawConfigParser()
|
||||||
self.SETTINGS.read_string(ini)
|
self.SETTINGS.read_string(ini)
|
||||||
|
|
@ -258,7 +256,6 @@ def roundup(x):
|
||||||
return math.ceil(x * d) / d
|
return math.ceil(x * d) / d
|
||||||
|
|
||||||
def formatFileSize(size, asInt=False, roundUp=False):
|
def formatFileSize(size, asInt=False, roundUp=False):
|
||||||
#size = size / 1024
|
|
||||||
if size == 1:
|
if size == 1:
|
||||||
return "{:d} Byte".format(size)
|
return "{:d} Byte".format(size)
|
||||||
elif size < 1024:
|
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])
|
info["tb_boot_sector"] = "{:s} (0x{:02X})".format(temp[buffer[pri_address + 0x1E]], buffer[pri_address + 0x1E])
|
||||||
except:
|
except:
|
||||||
info["tb_boot_sector"] = "0x{:02X}".format(buffer[pri_address + 0x1E])
|
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":
|
#elif "{:s}{:s}{:s}".format(chr(buffer[0x214]), chr(buffer[0x216]), chr(buffer[0x218])) == "PRI":
|
||||||
pass # TODO
|
# pass
|
||||||
|
|
||||||
info["device_size"] = int(math.pow(2, buffer[0x4E]))
|
info["device_size"] = int(math.pow(2, buffer[0x4E]))
|
||||||
info["buffer_size"] = buffer[0x56] << 8 | buffer[0x54]
|
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 ],
|
[ null, null, null ],
|
||||||
[ "SA", 0xFFFF, 0xFFFF ]
|
[ "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":[
|
"buffer_write":[
|
||||||
[ 0xAAA, 0xA9 ],
|
[ 0xAAA, 0xA9 ],
|
||||||
[ 0x555, 0x56 ],
|
[ 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 ]
|
[ 0x04, 0x04, 0x7D, 0x7D ]
|
||||||
],
|
],
|
||||||
"voltage":3.3,
|
"voltage":3.3,
|
||||||
|
"voltage_variants":true,
|
||||||
"flash_size":0x400000,
|
"flash_size":0x400000,
|
||||||
"start_addr":0x4000,
|
"start_addr":0x4000,
|
||||||
"first_bank":0,
|
"first_bank":0,
|
||||||
|
|
|
||||||
|
|
@ -62,8 +62,8 @@
|
||||||
[ "SA", 0xFF, 0xFF ]
|
[ "SA", 0xFF, 0xFF ]
|
||||||
],
|
],
|
||||||
"buffer_write":[
|
"buffer_write":[
|
||||||
[ 0x4AAA, 0xA9 ],
|
[ 0xAAA, 0xA9 ],
|
||||||
[ 0x4555, 0x56 ],
|
[ 0x555, 0x56 ],
|
||||||
[ "SA", 0x26 ],
|
[ "SA", 0x26 ],
|
||||||
[ "SA", "BS" ],
|
[ "SA", "BS" ],
|
||||||
[ "PA", "PD" ],
|
[ "PA", "PD" ],
|
||||||
|
|
|
||||||
|
|
@ -9,10 +9,6 @@
|
||||||
"start_addr":0x4000,
|
"start_addr":0x4000,
|
||||||
"first_bank":1,
|
"first_bank":1,
|
||||||
"write_pin":"WR",
|
"write_pin":"WR",
|
||||||
"sector_size":[
|
|
||||||
[0x2000, 8],
|
|
||||||
[0x10000, 63]
|
|
||||||
],
|
|
||||||
"chip_erase_timeout":40,
|
"chip_erase_timeout":40,
|
||||||
"mbc":0x03,
|
"mbc":0x03,
|
||||||
"pulse_reset_after_write":true,
|
"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()
|
rowDeviceInfo2 = QtWidgets.QHBoxLayout()
|
||||||
self.lblDevicePCBVer = QtWidgets.QLabel("PCB version:")
|
self.lblDevicePCBVer = QtWidgets.QLabel("PCB version:")
|
||||||
self.lblDevicePCBVer.setMinimumWidth(120)
|
self.lblDevicePCBVer.setMinimumWidth(120)
|
||||||
#self.lblDevicePCBVerResult = QtWidgets.QLabel("v1.4")
|
|
||||||
self.optDevicePCBVer14 = QtWidgets.QRadioButton("v1.4")
|
self.optDevicePCBVer14 = QtWidgets.QRadioButton("v1.4")
|
||||||
self.connect(self.optDevicePCBVer14, QtCore.SIGNAL("clicked()"), self.SetPCBVersion)
|
self.connect(self.optDevicePCBVer14, QtCore.SIGNAL("clicked()"), self.SetPCBVersion)
|
||||||
self.optDevicePCBVer14a = QtWidgets.QRadioButton("v1.4a")
|
self.optDevicePCBVer14a = QtWidgets.QRadioButton("v1.4a")
|
||||||
self.connect(self.optDevicePCBVer14a, QtCore.SIGNAL("clicked()"), self.SetPCBVersion)
|
self.connect(self.optDevicePCBVer14a, QtCore.SIGNAL("clicked()"), self.SetPCBVersion)
|
||||||
rowDeviceInfo2.addWidget(self.lblDevicePCBVer)
|
rowDeviceInfo2.addWidget(self.lblDevicePCBVer)
|
||||||
#rowDeviceInfo2.addWidget(self.lblDevicePCBVerResult)
|
|
||||||
rowDeviceInfo2.addWidget(self.optDevicePCBVer14)
|
rowDeviceInfo2.addWidget(self.optDevicePCBVer14)
|
||||||
rowDeviceInfo2.addWidget(self.optDevicePCBVer14a)
|
rowDeviceInfo2.addWidget(self.optDevicePCBVer14a)
|
||||||
rowDeviceInfo2.addStretch(1)
|
rowDeviceInfo2.addStretch(1)
|
||||||
|
|
@ -216,7 +214,6 @@ class FirmwareUpdaterWindow(QtWidgets.QDialog):
|
||||||
|
|
||||||
self.lblDeviceNameResult.setText(self.DEV_NAME)
|
self.lblDeviceNameResult.setText(self.DEV_NAME)
|
||||||
self.lblDeviceFWVerResult.setText(self.FW_VER)
|
self.lblDeviceFWVerResult.setText(self.FW_VER)
|
||||||
#self.lblDevicePCBVerResult.setText(self.PCB_VER)
|
|
||||||
if self.PCB_VER == "v1.4":
|
if self.PCB_VER == "v1.4":
|
||||||
self.optDevicePCBVer14.setChecked(True)
|
self.optDevicePCBVer14.setChecked(True)
|
||||||
elif self.PCB_VER == "v1.4a":
|
elif self.PCB_VER == "v1.4a":
|
||||||
|
|
@ -239,7 +236,7 @@ class FirmwareUpdaterWindow(QtWidgets.QDialog):
|
||||||
self.OFW_BUILDTS = self.INI.GetValue("fw_buildts")
|
self.OFW_BUILDTS = self.INI.GetValue("fw_buildts")
|
||||||
self.OFW_TEXT = self.INI.GetValue("fw_text")
|
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):
|
def run(self):
|
||||||
try:
|
try:
|
||||||
|
|
|
||||||
|
|
@ -10,6 +10,7 @@ from .RomFileAGB import RomFileAGB
|
||||||
from .Mapper import DMG_MBC, AGB_GPIO
|
from .Mapper import DMG_MBC, AGB_GPIO
|
||||||
from .Flashcart import Flashcart, Flashcart_DMG_MMSA
|
from .Flashcart import Flashcart, Flashcart_DMG_MMSA
|
||||||
from .Util import ANSI, dprint, bitswap, ParseCFI
|
from .Util import ANSI, dprint, bitswap, ParseCFI
|
||||||
|
from .GBMemory import GBMemoryMap
|
||||||
from . import Util
|
from . import Util
|
||||||
|
|
||||||
class GbxDevice:
|
class GbxDevice:
|
||||||
|
|
@ -93,6 +94,7 @@ class GbxDevice:
|
||||||
WORKER = None
|
WORKER = None
|
||||||
INFO = { "action":None, "last_action":None }
|
INFO = { "action":None, "last_action":None }
|
||||||
ERROR = False
|
ERROR = False
|
||||||
|
ERROR_ARGS = {}
|
||||||
CANCEL = False
|
CANCEL = False
|
||||||
CANCEL_ARGS = {}
|
CANCEL_ARGS = {}
|
||||||
SIGNAL = None
|
SIGNAL = None
|
||||||
|
|
@ -119,7 +121,6 @@ class GbxDevice:
|
||||||
for i in range(0, len(comports)):
|
for i in range(0, len(comports)):
|
||||||
if comports[i].vid == 0x1A86 and comports[i].pid == 0x7523:
|
if comports[i].vid == 0x1A86 and comports[i].pid == 0x7523:
|
||||||
ports.append(comports[i].device)
|
ports.append(comports[i].device)
|
||||||
#break
|
|
||||||
if len(ports) == 0: return False
|
if len(ports) == 0: return False
|
||||||
|
|
||||||
for i in range(0, len(ports)):
|
for i in range(0, len(ports)):
|
||||||
|
|
@ -301,7 +302,7 @@ class GbxDevice:
|
||||||
else:
|
else:
|
||||||
s = "{:s}{:d}".format(self.FW["cfw_id"], self.FW["fw_ver"])
|
s = "{:s}{:d}".format(self.FW["cfw_id"], self.FW["fw_ver"])
|
||||||
if more:
|
if more:
|
||||||
s += " (dated {:s})".format(self.FW["fw_dt"])
|
s += " ({:s})".format(self.FW["fw_dt"])
|
||||||
return s
|
return s
|
||||||
|
|
||||||
def GetPCBVersion(self):
|
def GetPCBVersion(self):
|
||||||
|
|
@ -316,7 +317,7 @@ class GbxDevice:
|
||||||
|
|
||||||
def GetFullNameExtended(self, more=False):
|
def GetFullNameExtended(self, more=False):
|
||||||
if more:
|
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:
|
else:
|
||||||
return "{:s} – Firmware {:s} ({:s})".format(self.GetFullName(), self.GetFirmwareVersion(), self.PORT)
|
return "{:s} – Firmware {:s} ({:s})".format(self.GetFullName(), self.GetFirmwareVersion(), self.PORT)
|
||||||
|
|
||||||
|
|
@ -356,10 +357,14 @@ class GbxDevice:
|
||||||
tb_stack = traceback.extract_stack()
|
tb_stack = traceback.extract_stack()
|
||||||
stack = tb_stack[len(tb_stack)-2] # caller only
|
stack = tb_stack[len(tb_stack)-2] # caller only
|
||||||
if stack.name == "_write": stack = tb_stack[len(tb_stack)-3]
|
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))
|
if buffer is False:
|
||||||
self.CANCEL = True
|
dprint("Timeout error ({:s}(), line {:d})".format(stack.name, stack.lineno))
|
||||||
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."}
|
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.ERROR = True
|
||||||
|
self.CANCEL = True
|
||||||
return False
|
return False
|
||||||
|
|
||||||
return buffer
|
return buffer
|
||||||
|
|
@ -666,18 +671,16 @@ class GbxDevice:
|
||||||
if mbc == 0x20: # MBC6
|
if mbc == 0x20: # MBC6
|
||||||
save_size = 1081344
|
save_size = 1081344
|
||||||
save_type = 7
|
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)
|
return (info, save_size, save_type, save_chip, sram_unstable, cart_types, cart_type_id, cfi_s, cfi, flash_id)
|
||||||
elif mbc == 0x22: # MBC7
|
elif mbc == 0x22: # MBC7
|
||||||
max_size = 512
|
max_size = 512
|
||||||
elif mbc == 0xFD: # TAMA5
|
elif mbc == 0xFD: # TAMA5
|
||||||
save_size = 32
|
save_size = 32
|
||||||
save_type = 10
|
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)
|
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 }
|
args = { 'mode':2, 'path':None, 'mbc':mbc, 'save_type':max_size, 'rtc':False }
|
||||||
elif self.MODE == "AGB":
|
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)
|
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_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]
|
save_chip = Util.AGB_Flash_Save_Chips[flash_save_id]
|
||||||
if save_size == 131072:
|
if save_size == 131072:
|
||||||
save_type = 7
|
save_type = 5
|
||||||
elif save_size == 65536:
|
elif save_size == 65536:
|
||||||
save_type = 6
|
save_type = 4
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
|
||||||
if save_type is None:
|
if save_type is None:
|
||||||
if info["dacs_8m"] is True:
|
if info["dacs_8m"] is True:
|
||||||
save_size = 1032192
|
save_size = 1032192
|
||||||
save_type = 8
|
save_type = 6
|
||||||
elif save_size > 256:
|
elif save_size > 256: # SRAM
|
||||||
save_type = Util.AGB_Header_Save_Sizes.index(save_size)
|
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:
|
else:
|
||||||
dprint("Testing EEPROM")
|
dprint("Testing EEPROM")
|
||||||
# Check for 4K EEPROM
|
# Check for 4K EEPROM
|
||||||
|
|
@ -745,7 +755,6 @@ class GbxDevice:
|
||||||
save_size = 512
|
save_size = 512
|
||||||
|
|
||||||
self._write(self.DEVICE_CMD["DMG_MBC_RESET"], wait=True)
|
self._write(self.DEVICE_CMD["DMG_MBC_RESET"], wait=True)
|
||||||
#if self.CanPowerCycleCart(): self.CartPowerCycle()
|
|
||||||
self.INFO["last_action"] = 0
|
self.INFO["last_action"] = 0
|
||||||
self.INFO["action"] = None
|
self.INFO["action"] = None
|
||||||
|
|
||||||
|
|
@ -880,7 +889,6 @@ class GbxDevice:
|
||||||
if isinstance(temp, int): temp = bytearray([temp])
|
if isinstance(temp, int): temp = bytearray([temp])
|
||||||
if temp is False or len(temp) != length: return bytearray()
|
if temp is False or len(temp) != length: return bytearray()
|
||||||
buffer += temp
|
buffer += temp
|
||||||
#if self.INFO["action"] == self.ACTIONS["SAVE_READ"] and not self.NO_PROG_UPDATE:
|
|
||||||
if not self.NO_PROG_UPDATE:
|
if not self.NO_PROG_UPDATE:
|
||||||
self.SetProgress({"action":"READ", "bytes_added":len(temp)})
|
self.SetProgress({"action":"READ", "bytes_added":len(temp)})
|
||||||
|
|
||||||
|
|
@ -899,7 +907,6 @@ class GbxDevice:
|
||||||
temp = self._read(length)
|
temp = self._read(length)
|
||||||
if isinstance(temp, int): temp = bytearray([temp])
|
if isinstance(temp, int): temp = bytearray([temp])
|
||||||
buffer += temp
|
buffer += temp
|
||||||
#if self.INFO["action"] == self.ACTIONS["SAVE_READ"] and not self.NO_PROG_UPDATE:
|
|
||||||
if not self.NO_PROG_UPDATE:
|
if not self.NO_PROG_UPDATE:
|
||||||
self.SetProgress({"action":"READ", "bytes_added":len(temp)})
|
self.SetProgress({"action":"READ", "bytes_added":len(temp)})
|
||||||
|
|
||||||
|
|
@ -1000,7 +1007,6 @@ class GbxDevice:
|
||||||
self._cart_write(address + length - 1, 0x00)
|
self._cart_write(address + length - 1, 0x00)
|
||||||
while True:
|
while True:
|
||||||
sr = self._cart_read(address + length - 1)
|
sr = self._cart_read(address + length - 1)
|
||||||
#print("sr=0x{:X}".format(sr))
|
|
||||||
if sr == 0x80: break
|
if sr == 0x80: break
|
||||||
time.sleep(0.001)
|
time.sleep(0.001)
|
||||||
|
|
||||||
|
|
@ -1092,7 +1098,8 @@ class GbxDevice:
|
||||||
ret = self._write(data, wait=True)
|
ret = self._write(data, wait=True)
|
||||||
|
|
||||||
if ret not in (0x01, 0x03):
|
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
|
self.SKIPPING = False
|
||||||
return False
|
return False
|
||||||
pos += len(data)
|
pos += len(data)
|
||||||
|
|
@ -1190,7 +1197,6 @@ class GbxDevice:
|
||||||
self._cart_write(address + length - 1, 0xFF)
|
self._cart_write(address + length - 1, 0xFF)
|
||||||
while True:
|
while True:
|
||||||
sr = self._cart_read(address + length - 1)
|
sr = self._cart_read(address + length - 1)
|
||||||
#print("sr=0x{:X}".format(sr))
|
|
||||||
if sr == 0x80: break
|
if sr == 0x80: break
|
||||||
time.sleep(0.001)
|
time.sleep(0.001)
|
||||||
|
|
||||||
|
|
@ -1203,10 +1209,6 @@ class GbxDevice:
|
||||||
|
|
||||||
def WriteROM_DMG_MBC5_32M_FLASH(self, address, buffer, bank):
|
def WriteROM_DMG_MBC5_32M_FLASH(self, address, buffer, bank):
|
||||||
length = len(buffer)
|
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
|
max_length = 128
|
||||||
num = math.ceil(length / max_length)
|
num = math.ceil(length / max_length)
|
||||||
if length > max_length: 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]))
|
dprint("*** Now checking: {:s}\n".format(flashcart_meta["names"][0]))
|
||||||
|
|
||||||
if self.MODE == "DMG":
|
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":
|
if flashcart_meta["write_pin"] == "WR":
|
||||||
we = 0x01 # FLASH_WE_PIN_WR
|
we = 0x01 # FLASH_WE_PIN_WR
|
||||||
elif flashcart_meta["write_pin"] in ("AUDIO", "VIN"):
|
elif flashcart_meta["write_pin"] in ("AUDIO", "VIN"):
|
||||||
|
|
@ -1396,7 +1397,6 @@ class GbxDevice:
|
||||||
if "method" in cfi: break
|
if "method" in cfi: break
|
||||||
for method in flash_commands:
|
for method in flash_commands:
|
||||||
if self.MODE == "DMG":
|
if self.MODE == "DMG":
|
||||||
#self._set_fw_variable("FLASH_COMMANDS_BANK_1", "flash_commands_on_bank_1" in flashcart_meta)
|
|
||||||
if we == "WR":
|
if we == "WR":
|
||||||
self._set_fw_variable("FLASH_WE_PIN", 0x01) # FLASH_WE_PIN_WR
|
self._set_fw_variable("FLASH_WE_PIN", 0x01) # FLASH_WE_PIN_WR
|
||||||
elif we in ("AUDIO", "VIN"):
|
elif we in ("AUDIO", "VIN"):
|
||||||
|
|
@ -1555,7 +1555,7 @@ class GbxDevice:
|
||||||
if not line_exists: flash_id_lines.append([method_string, flash_id])
|
if not line_exists: flash_id_lines.append([method_string, flash_id])
|
||||||
for i in range(0, len(method['reset'])):
|
for i in range(0, len(method['reset'])):
|
||||||
self._cart_write(method['reset'][i][0], method['reset'][i][1], flashcart=True)
|
self._cart_write(method['reset'][i][0], method['reset'][i][1], flashcart=True)
|
||||||
|
|
||||||
if self.MODE == "DMG":
|
if self.MODE == "DMG":
|
||||||
self._write(self.DEVICE_CMD["SET_VOLTAGE_5V"])
|
self._write(self.DEVICE_CMD["SET_VOLTAGE_5V"])
|
||||||
time.sleep(0.25)
|
time.sleep(0.25)
|
||||||
|
|
@ -1572,7 +1572,7 @@ class GbxDevice:
|
||||||
flash_id += "\n"
|
flash_id += "\n"
|
||||||
|
|
||||||
flash_id = rom_string + flash_id
|
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)
|
return (flash_id, cfi_info, cfi)
|
||||||
|
|
||||||
#################################################################
|
#################################################################
|
||||||
|
|
@ -1612,7 +1612,7 @@ class GbxDevice:
|
||||||
if len(args["path"]) > 0:
|
if len(args["path"]) > 0:
|
||||||
file = open(args["path"], "wb")
|
file = open(args["path"], "wb")
|
||||||
|
|
||||||
self.FAST_READ = True #args["fast_read_mode"]
|
self.FAST_READ = True
|
||||||
|
|
||||||
flashcart = False
|
flashcart = False
|
||||||
supported_carts = list(self.SUPPORTED_CARTS[self.MODE].values())
|
supported_carts = list(self.SUPPORTED_CARTS[self.MODE].values())
|
||||||
|
|
@ -1643,9 +1643,7 @@ class GbxDevice:
|
||||||
else:
|
else:
|
||||||
_mbc.EnableMapper()
|
_mbc.EnableMapper()
|
||||||
|
|
||||||
#rom_banks = args['rom_banks']
|
|
||||||
rom_size = args["rom_size"]
|
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)
|
rom_banks = _mbc.GetROMBanks(rom_size)
|
||||||
size = _mbc.GetROMSize()
|
size = _mbc.GetROMSize()
|
||||||
|
|
||||||
|
|
@ -1659,7 +1657,6 @@ class GbxDevice:
|
||||||
if "verify_write" in args:
|
if "verify_write" in args:
|
||||||
rom_banks = math.ceil(len(args["verify_write"]) / cart_type["flash_bank_size"])
|
rom_banks = math.ceil(len(args["verify_write"]) / cart_type["flash_bank_size"])
|
||||||
else:
|
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"])
|
rom_banks = math.ceil(size / cart_type["flash_bank_size"])
|
||||||
else:
|
else:
|
||||||
rom_banks = 1
|
rom_banks = 1
|
||||||
|
|
@ -1706,6 +1703,7 @@ class GbxDevice:
|
||||||
if file is not None: file.close()
|
if file is not None: file.close()
|
||||||
except:
|
except:
|
||||||
pass
|
pass
|
||||||
|
if self.CanPowerCycleCart(): self.CartPowerCycle()
|
||||||
return
|
return
|
||||||
|
|
||||||
if (self.MODE == "AGB" and self.INFO["3d_memory"]):
|
if (self.MODE == "AGB" and self.INFO["3d_memory"]):
|
||||||
|
|
@ -1802,7 +1800,7 @@ class GbxDevice:
|
||||||
|
|
||||||
# Prepare some stuff
|
# Prepare some stuff
|
||||||
command = None
|
command = None
|
||||||
empty_data_byte = 0xFF
|
empty_data_byte = 0x00
|
||||||
extra_size = 0
|
extra_size = 0
|
||||||
audio_low = False
|
audio_low = False
|
||||||
if self.MODE == "DMG":
|
if self.MODE == "DMG":
|
||||||
|
|
@ -1818,11 +1816,11 @@ class GbxDevice:
|
||||||
self._set_fw_variable("DMG_READ_CS_PULSE", 1)
|
self._set_fw_variable("DMG_READ_CS_PULSE", 1)
|
||||||
_mbc.EnableMapper()
|
_mbc.EnableMapper()
|
||||||
self._set_fw_variable("DMG_READ_CS_PULSE", 0)
|
self._set_fw_variable("DMG_READ_CS_PULSE", 0)
|
||||||
empty_data_byte = 0x00
|
|
||||||
buffer_len = 0x20
|
buffer_len = 0x20
|
||||||
elif _mbc.GetName() == "MBC7":
|
elif _mbc.GetName() == "MBC7":
|
||||||
buffer_len = save_size
|
buffer_len = save_size
|
||||||
elif _mbc.GetName() == "MBC6":
|
elif _mbc.GetName() == "MBC6":
|
||||||
|
empty_data_byte = 0xFF
|
||||||
audio_low = True
|
audio_low = True
|
||||||
self._set_fw_variable("FLASH_METHOD", 0x04) # FLASH_METHOD_DMG_MBC6
|
self._set_fw_variable("FLASH_METHOD", 0x04) # FLASH_METHOD_DMG_MBC6
|
||||||
self._set_fw_variable("FLASH_WE_PIN", 0x01) # WR
|
self._set_fw_variable("FLASH_WE_PIN", 0x01) # WR
|
||||||
|
|
@ -1860,13 +1858,15 @@ class GbxDevice:
|
||||||
buffer_len = 0x40
|
buffer_len = 0x40
|
||||||
else:
|
else:
|
||||||
buffer_len = 0x100
|
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()
|
ret = self.ReadFlashSaveID()
|
||||||
if ret is False:
|
if ret is False:
|
||||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"Couldn’t detect the save data flash chip.", "abortable":False})
|
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"Couldn’t detect the save data flash chip.", "abortable":False})
|
||||||
return False
|
return False
|
||||||
(buffer_len, agb_flash_chip, _) = ret
|
(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
|
# Read Chip ID
|
||||||
ram_banks = 1
|
ram_banks = 1
|
||||||
self._cart_write(0, 0x90)
|
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"], 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
|
[ 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"], 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"] ], # 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"], 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]
|
command = commands[args["save_type"]][args["mode"] - 2]
|
||||||
if args["rtc"] is True:
|
if args["rtc"] is True:
|
||||||
|
|
@ -1960,14 +1960,14 @@ class GbxDevice:
|
||||||
elif self.MODE == "AGB":
|
elif self.MODE == "AGB":
|
||||||
start_address = 0
|
start_address = 0
|
||||||
bank_size = 0x10000
|
bank_size = 0x10000
|
||||||
if args["save_type"] == 8: # DACS
|
if args["save_type"] == 6: # DACS
|
||||||
bank_size = 0xFC000
|
bank_size = 0xFC000
|
||||||
end_address = 0xFC000
|
end_address = 0xFC000
|
||||||
else:
|
else:
|
||||||
end_address = min(save_size, bank_size)
|
end_address = min(save_size, bank_size)
|
||||||
|
|
||||||
if 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))
|
dprint("Switching to FLASH bank {:d}".format(bank))
|
||||||
cmds = [
|
cmds = [
|
||||||
[ 0x5555, 0xAA ],
|
[ 0x5555, 0xAA ],
|
||||||
|
|
@ -1976,14 +1976,13 @@ class GbxDevice:
|
||||||
[ 0, bank ]
|
[ 0, bank ]
|
||||||
]
|
]
|
||||||
self._cart_write_flash(cmds)
|
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))
|
dprint("Switching to SRAM bank {:d}".format(bank))
|
||||||
self._cart_write(0x1000000, bank)
|
self._cart_write(0x1000000, bank)
|
||||||
else:
|
else:
|
||||||
dprint("Unknown bank switching method")
|
dprint("Unknown bank switching method")
|
||||||
time.sleep(0.1)
|
time.sleep(0.05)
|
||||||
|
|
||||||
#buffer_offset = bank * bank_size
|
|
||||||
max_length = 64
|
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))
|
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
|
pos = start_address
|
||||||
|
|
@ -1993,6 +1992,7 @@ class GbxDevice:
|
||||||
cancel_args.update(self.CANCEL_ARGS)
|
cancel_args.update(self.CANCEL_ARGS)
|
||||||
self.CANCEL_ARGS = {}
|
self.CANCEL_ARGS = {}
|
||||||
self.SetProgress(cancel_args)
|
self.SetProgress(cancel_args)
|
||||||
|
if self.CanPowerCycleCart(): self.CartPowerCycle()
|
||||||
return
|
return
|
||||||
|
|
||||||
if args["mode"] == 2: # Backup
|
if args["mode"] == 2: # Backup
|
||||||
|
|
@ -2004,7 +2004,7 @@ class GbxDevice:
|
||||||
temp = self.ReadRAM_TAMA5()
|
temp = self.ReadRAM_TAMA5()
|
||||||
elif self.MODE == "AGB" and args["save_type"] in (1, 2): # EEPROM
|
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)
|
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)
|
temp = self.ReadROM(address=0x1F00000+pos, length=buffer_len, skip_init=False, max_length=max_length)
|
||||||
else:
|
else:
|
||||||
temp = self.ReadRAM(address=pos, length=buffer_len, command=command, max_length=max_length)
|
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])
|
self.WriteRAM_TAMA5(buffer=buffer[buffer_offset:buffer_offset+buffer_len])
|
||||||
elif self.MODE == "AGB" and args["save_type"] in (1, 2): # EEPROM
|
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)
|
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)
|
sector_address = int(pos / buffer_len)
|
||||||
if agb_flash_chip == 0x1F3D: # Atmel AT29LV512
|
if agb_flash_chip == 0x1F3D: # Atmel AT29LV512
|
||||||
self.WriteRAM(address=int(pos/128), buffer=buffer[buffer_offset:buffer_offset+buffer_len], command=command)
|
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:
|
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})
|
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
|
return False
|
||||||
self.WriteRAM(address=pos, buffer=buffer[buffer_offset:buffer_offset+buffer_len], command=command)
|
if buffer[buffer_offset:buffer_offset+buffer_len] != bytearray([0xFF] * buffer_len):
|
||||||
elif self.MODE == "AGB" and args["save_type"] == 8: # DACS
|
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):
|
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
|
sector_address = pos+0x1F00000
|
||||||
dprint("sector_address:", hex(sector_address))
|
dprint("sector_address:", hex(sector_address))
|
||||||
|
|
@ -2179,7 +2180,7 @@ class GbxDevice:
|
||||||
return True
|
return True
|
||||||
|
|
||||||
def _FlashROM(self, args):
|
def _FlashROM(self, args):
|
||||||
self.FAST_READ = True #args["fast_read_mode"]
|
self.FAST_READ = True
|
||||||
|
|
||||||
if "buffer" in args:
|
if "buffer" in args:
|
||||||
data_import = args["buffer"]
|
data_import = args["buffer"]
|
||||||
|
|
@ -2254,14 +2255,24 @@ class GbxDevice:
|
||||||
if cart_type["command_set"] == "GBMEMORY":
|
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)
|
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:
|
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()
|
with open(os.path.splitext(args["path"])[0] + ".map", "rb") as file: args["buffer_map"] = file.read()
|
||||||
except:
|
else:
|
||||||
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})
|
temp = data_import
|
||||||
return False
|
if len(temp) == 0: temp = bytearray([0xFF] * 0x180)
|
||||||
#with open(args["path"], "rb") as f: rom_data = bytearray(f.read())
|
try:
|
||||||
#gbmem = GBMemory(None, rom_data, None)
|
gbmem = GBMemoryMap(rom=temp)
|
||||||
#args["buffer_map"] = gbmem.GetMapData()
|
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 = copy.copy(args["buffer_map"])
|
||||||
data_map_import = bytearray(data_map_import)
|
data_map_import = bytearray(data_map_import)
|
||||||
dprint("Hidden sector data loaded")
|
dprint("Hidden sector data loaded")
|
||||||
|
|
@ -2305,8 +2316,6 @@ class GbxDevice:
|
||||||
args["mbc"] = 0x1B # MBC5+SRAM+BATTERY
|
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)
|
_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)
|
self._set_fw_variable("FLASH_PULSE_RESET", 1 if flashcart.PulseResetAfterWrite() else 0)
|
||||||
|
|
||||||
rom_banks = math.ceil(len(data_import) / _mbc.GetROMBankSize())
|
rom_banks = math.ceil(len(data_import) / _mbc.GetROMBankSize())
|
||||||
|
|
@ -2433,7 +2442,6 @@ class GbxDevice:
|
||||||
(verified, flash_id) = flashcart.VerifyFlashID()
|
(verified, flash_id) = flashcart.VerifyFlashID()
|
||||||
if not verified:
|
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)))
|
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 Flash ID
|
||||||
|
|
||||||
# ↓↓↓ Read Sector Map
|
# ↓↓↓ Read Sector Map
|
||||||
|
|
@ -2456,15 +2464,12 @@ class GbxDevice:
|
||||||
# ↓↓↓ Chip erase
|
# ↓↓↓ Chip erase
|
||||||
chip_erase = False
|
chip_erase = False
|
||||||
if flashcart.SupportsChipErase():
|
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
|
chip_erase = False
|
||||||
else:
|
else:
|
||||||
chip_erase = True
|
chip_erase = True
|
||||||
#if flashcart.FlashCommandsOnBank1():
|
|
||||||
# _mbc.SelectBankROM(1)
|
|
||||||
if flashcart.ChipErase() is False:
|
if flashcart.ChipErase() is False:
|
||||||
return False
|
return False
|
||||||
#_mbc.SelectBankROM(0)
|
|
||||||
elif flashcart.SupportsSectorErase() is False:
|
elif flashcart.SupportsSectorErase() is False:
|
||||||
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"No erase method available.", "abortable":False})
|
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"No erase method available.", "abortable":False})
|
||||||
return False
|
return False
|
||||||
|
|
@ -2524,7 +2529,8 @@ class GbxDevice:
|
||||||
cancel_args.update(self.CANCEL_ARGS)
|
cancel_args.update(self.CANCEL_ARGS)
|
||||||
self.CANCEL_ARGS = {}
|
self.CANCEL_ARGS = {}
|
||||||
self.SetProgress(cancel_args)
|
self.SetProgress(cancel_args)
|
||||||
return False
|
if self.CanPowerCycleCart(): self.CartPowerCycle()
|
||||||
|
return
|
||||||
|
|
||||||
if buffer_pos >= len(data_import): break
|
if buffer_pos >= len(data_import): break
|
||||||
|
|
||||||
|
|
@ -2554,7 +2560,12 @@ class GbxDevice:
|
||||||
else:
|
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)
|
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:
|
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.CANCEL = True
|
||||||
self.ERROR = True
|
self.ERROR = True
|
||||||
continue
|
continue
|
||||||
|
|
@ -2562,9 +2573,8 @@ class GbxDevice:
|
||||||
skip_init = True
|
skip_init = True
|
||||||
|
|
||||||
buffer_pos += buffer_len
|
buffer_pos += buffer_len
|
||||||
self.SetProgress({"action":"UPDATE_POS", "pos":buffer_pos})
|
|
||||||
|
|
||||||
pos += buffer_len
|
pos += buffer_len
|
||||||
|
self.SetProgress({"action":"UPDATE_POS", "pos":buffer_pos})
|
||||||
|
|
||||||
# Hidden Sector
|
# Hidden Sector
|
||||||
if command_set_type == "GBMEMORY":
|
if command_set_type == "GBMEMORY":
|
||||||
|
|
@ -2586,10 +2596,6 @@ class GbxDevice:
|
||||||
self.SetProgress({"action":"INITIALIZE", "method":"ROM_WRITE_VERIFY", "size":buffer_pos})
|
self.SetProgress({"action":"INITIALIZE", "method":"ROM_WRITE_VERIFY", "size":buffer_pos})
|
||||||
|
|
||||||
verify_args = copy.copy(args)
|
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
|
start_address = 0
|
||||||
end_address = buffer_pos
|
end_address = buffer_pos
|
||||||
|
|
@ -2599,9 +2605,8 @@ class GbxDevice:
|
||||||
verified_size = self._BackupROM(verify_args)
|
verified_size = self._BackupROM(verify_args)
|
||||||
if self.CANCEL is True:
|
if self.CANCEL is True:
|
||||||
pass
|
pass
|
||||||
#elif (verified_size is not True) and (buffer_pos != verified_size):
|
|
||||||
elif (verified_size is not True) and (len(data_import) != 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
|
return False
|
||||||
else:
|
else:
|
||||||
verified = True
|
verified = True
|
||||||
|
|
|
||||||
|
|
@ -119,7 +119,7 @@ class GbxDevice:
|
||||||
"AUDIO_HIGH":'8',
|
"AUDIO_HIGH":'8',
|
||||||
"AUDIO_LOW":'9',
|
"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 = {}
|
SUPPORTED_CARTS = {}
|
||||||
|
|
||||||
FW = []
|
FW = []
|
||||||
|
|
@ -212,11 +212,11 @@ class GbxDevice:
|
||||||
self.DEVICE = None
|
self.DEVICE = None
|
||||||
continue
|
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"])
|
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.PORT = ports[i]
|
||||||
self.DEVICE.timeout = 1
|
self.DEVICE.timeout = 1
|
||||||
|
|
@ -1120,7 +1120,7 @@ class GbxDevice:
|
||||||
return False
|
return False
|
||||||
return True
|
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.")
|
if not self.IsConnected(): raise Exception("Couldn’t access the the device.")
|
||||||
data = {}
|
data = {}
|
||||||
self.POS = 0
|
self.POS = 0
|
||||||
|
|
@ -1244,7 +1244,7 @@ class GbxDevice:
|
||||||
# Firmware check R26+
|
# Firmware check R26+
|
||||||
# Firmware check CFW
|
# 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
|
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
|
return False
|
||||||
# Firmware check CFW
|
# Firmware check CFW
|
||||||
|
|
||||||
|
|
@ -1539,19 +1539,19 @@ class GbxDevice:
|
||||||
save_size = 32 * 1024
|
save_size = 32 * 1024
|
||||||
read_command = 'GBA_READ_SRAM'
|
read_command = 'GBA_READ_SRAM'
|
||||||
write_command = 'GBA_WRITE_SRAM'
|
write_command = 'GBA_WRITE_SRAM'
|
||||||
elif save_type == 4: # SRAM 64 KB
|
elif save_type == 7: # SRAM 64 KB
|
||||||
save_size = 64 * 1024
|
save_size = 64 * 1024
|
||||||
read_command = 'GBA_READ_SRAM'
|
read_command = 'GBA_READ_SRAM'
|
||||||
write_command = 'GBA_WRITE_SRAM'
|
write_command = 'GBA_WRITE_SRAM'
|
||||||
elif save_type == 5: # SRAM 128 KB
|
elif save_type == 8: # SRAM 128 KB
|
||||||
save_size = 128 * 1024
|
save_size = 128 * 1024
|
||||||
read_command = 'GBA_READ_SRAM'
|
read_command = 'GBA_READ_SRAM'
|
||||||
write_command = 'GBA_WRITE_SRAM'
|
write_command = 'GBA_WRITE_SRAM'
|
||||||
bank_count = 2
|
bank_count = 2
|
||||||
elif save_type == 6: # FLASH 64 KB
|
elif save_type == 4: # FLASH 64 KB
|
||||||
save_size = 64 * 1024
|
save_size = 64 * 1024
|
||||||
read_command = 'GBA_READ_SRAM'
|
read_command = 'GBA_READ_SRAM'
|
||||||
elif save_type == 7: # FLASH 128 KB
|
elif save_type == 5: # FLASH 128 KB
|
||||||
save_size = 128 * 1024
|
save_size = 128 * 1024
|
||||||
read_command = 'GBA_READ_SRAM'
|
read_command = 'GBA_READ_SRAM'
|
||||||
bank_count = 2
|
bank_count = 2
|
||||||
|
|
@ -1560,7 +1560,7 @@ class GbxDevice:
|
||||||
|
|
||||||
# Get Save Flash Manufacturer
|
# Get Save Flash Manufacturer
|
||||||
maker_id = None
|
maker_id = None
|
||||||
if save_type == 6 or save_type == 7:
|
if save_type == 4 or save_type == 5:
|
||||||
maker_id = self.ReadFlashSaveMakerID()
|
maker_id = self.ReadFlashSaveMakerID()
|
||||||
if maker_id == "ATMEL" and mode == 3:
|
if maker_id == "ATMEL" and mode == 3:
|
||||||
transfer_size = 128
|
transfer_size = 128
|
||||||
|
|
@ -1611,9 +1611,9 @@ class GbxDevice:
|
||||||
if endAddr > (startAddr + save_size): endAddr = startAddr + save_size
|
if endAddr > (startAddr + save_size): endAddr = startAddr + save_size
|
||||||
if save_type == 1 or save_type == 2: # EEPROM
|
if save_type == 1 or save_type == 2: # EEPROM
|
||||||
self.set_number(eeprom_size, self.DEVICE_CMD["GBA_SET_EEPROM_SIZE"])
|
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)
|
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(bank, self.DEVICE_CMD["GBA_FLASH_SET_BANK"])
|
||||||
|
|
||||||
self.set_number(startAddr, self.DEVICE_CMD["SET_START_ADDRESS"])
|
self.set_number(startAddr, self.DEVICE_CMD["SET_START_ADDRESS"])
|
||||||
|
|
@ -1668,7 +1668,7 @@ class GbxDevice:
|
||||||
self.wait_for_ack()
|
self.wait_for_ack()
|
||||||
|
|
||||||
elif self.MODE == "AGB":
|
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":
|
if maker_id == "ATMEL":
|
||||||
self.gbx_flash_write_data_bytes(self.DEVICE_CMD["GBA_FLASH_WRITE_ATMEL"], data)
|
self.gbx_flash_write_data_bytes(self.DEVICE_CMD["GBA_FLASH_WRITE_ATMEL"], data)
|
||||||
self.wait_for_ack()
|
self.wait_for_ack()
|
||||||
|
|
@ -1809,9 +1809,9 @@ class GbxDevice:
|
||||||
|
|
||||||
elif self.MODE == "AGB":
|
elif self.MODE == "AGB":
|
||||||
if bank > 0:
|
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)
|
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"])
|
self.set_number(0, self.DEVICE_CMD["GBA_FLASH_SET_BANK"])
|
||||||
|
|
||||||
if mode == 2:
|
if mode == 2:
|
||||||
|
|
@ -1918,20 +1918,20 @@ class GbxDevice:
|
||||||
# Firmware check R23+
|
# Firmware check R23+
|
||||||
# Firmware check R25+
|
# 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
|
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
|
return False
|
||||||
# Firmware check R25+
|
# Firmware check R25+
|
||||||
# Firmware check R28+
|
# 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
|
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
|
return False
|
||||||
# Firmware check R25+
|
# Firmware check R25+
|
||||||
# Firmware check
|
# 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]]:
|
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
|
return False
|
||||||
if self.MODE == "AGB" and "buffer_size" in flashcart_meta and flashcart_meta["buffer_size"] > 256:
|
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
|
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]]:
|
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.")
|
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"]
|
del flashcart_meta["commands"]["buffer_write"]
|
||||||
|
|
||||||
#if "dmg-mmsa-jpn" in flashcart_meta:
|
#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
|
# return False
|
||||||
# Firmware check
|
# Firmware check
|
||||||
#dprint(flashcart_meta)
|
#dprint(flashcart_meta)
|
||||||
|
|
@ -2024,7 +2024,7 @@ class GbxDevice:
|
||||||
|
|
||||||
# Check if write command exists and quit if not
|
# 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"]:
|
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
|
return False
|
||||||
|
|
||||||
# Chip Erase
|
# Chip Erase
|
||||||
|
|
@ -2252,7 +2252,7 @@ class GbxDevice:
|
||||||
pos += 32
|
pos += 32
|
||||||
|
|
||||||
else:
|
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
|
return False
|
||||||
|
|
||||||
elif self.MODE == "AGB":
|
elif self.MODE == "AGB":
|
||||||
|
|
@ -2359,7 +2359,7 @@ class GbxDevice:
|
||||||
pos += 256
|
pos += 256
|
||||||
|
|
||||||
else:
|
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
|
return False
|
||||||
|
|
||||||
elif "single_write" in flashcart_meta["commands"]:
|
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
|
- 29LV Series Flash BOY with 29LV160DB
|
||||||
- BUNG Doctor GB Card 64M
|
- BUNG Doctor GB Card 64M
|
||||||
|
- DIY cart with AM29F010
|
||||||
- DIY cart with AM29F016
|
- DIY cart with AM29F016
|
||||||
- DIY cart with AM29F032
|
- DIY cart with AM29F032
|
||||||
|
- DIY cart with AM29F040
|
||||||
|
- DIY cart with AM29F080
|
||||||
- DIY cart with AT49F040
|
- DIY cart with AT49F040
|
||||||
- DIY cart with MBC1 and AM29F080
|
- DIY cart with MX29LV640
|
||||||
- DIY cart with MBC3 and MX29LV640
|
- DIY cart with SST39SF040
|
||||||
- DMG-MBC5-32M-FLASH Development Cartridge, E201264
|
- DMG-MBC5-32M-FLASH Development Cartridge, E201264
|
||||||
- Ferrante Crafts cart with SST39SF010A
|
- Ferrante Crafts cart with SST39SF010A
|
||||||
- GB-CART32K-A with SST39SF020A
|
- 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 GL128S
|
||||||
- AGB-E05-01 with MSP55LV128M
|
- AGB-E05-01 with MSP55LV128M
|
||||||
- AGB-E05-01 with MX29GL128FHT2I-90G
|
- AGB-E05-01 with MX29GL128FHT2I-90G
|
||||||
|
- AGB-E05-01 with S29GL064
|
||||||
- AGB-E05-02 with JS28F128
|
- AGB-E05-02 with JS28F128
|
||||||
- AGB-E05-02 with M29W128FH
|
- AGB-E05-02 with M29W128FH
|
||||||
- AGB-E05-02 with M29W128GH
|
- 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 M29W128GH
|
||||||
- AGB-E20-30 with S29GL256N10TFI01
|
- AGB-E20-30 with S29GL256N10TFI01
|
||||||
- AGB-SD-E05 with MSP55LV128
|
- AGB-SD-E05 with MSP55LV128
|
||||||
|
- B100 with MX29LV640ET
|
||||||
- B104 with MSP55LV128
|
- B104 with MSP55LV128
|
||||||
- B11 with 26L6420MC-90
|
- B11 with 26L6420MC-90
|
||||||
|
- B54 with MX29LV320ET
|
||||||
- BX2006_0106_NEW with S29GL128N10TFI01
|
- BX2006_0106_NEW with S29GL128N10TFI01
|
||||||
- BX2006_TSOP_64BALL with GL128S
|
- BX2006_TSOP_64BALL with GL128S
|
||||||
- BX2006_TSOP_64BALL with GL256S
|
- 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)
|
- dyf2007 (flash chip info)
|
||||||
- easthighNerd (feature suggestions)
|
- easthighNerd (feature suggestions)
|
||||||
- EchelonPrime (flash chip info)
|
- EchelonPrime (flash chip info)
|
||||||
|
- EmperorOfTigers (bug reports)
|
||||||
- endrift (research, mGBA emulator)
|
- endrift (research, mGBA emulator)
|
||||||
- eveningmoose (flash chip info)
|
- eveningmoose (flash chip info)
|
||||||
- frarees (bug reports)
|
- 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)
|
- Jayro (flash chip info)
|
||||||
- JFox (help with properly packaging the app for pip, Linux help)
|
- JFox (help with properly packaging the app for pip, Linux help)
|
||||||
- joyrider3774 (flash chip info)
|
- joyrider3774 (flash chip info)
|
||||||
|
- JS7457 (flash chip info)
|
||||||
- julgr (macOS help, testing)
|
- julgr (macOS help, testing)
|
||||||
- litlemoran (flash chip info)
|
- litlemoran (flash chip info)
|
||||||
- LovelyA72 (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(
|
setuptools.setup(
|
||||||
name="FlashGBX",
|
name="FlashGBX",
|
||||||
version="3.6",
|
version="3.7",
|
||||||
author="Lesserkuma",
|
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.",
|
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",
|
url="https://github.com/lesserkuma/FlashGBX",
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue
Block a user