mirror of
https://github.com/lesserkuma/FlashGBX.git
synced 2026-03-21 17:44:30 -05:00
3.12
This commit is contained in:
parent
a8ce26c54e
commit
2dffc534ca
|
|
@ -1,4 +1,10 @@
|
|||
# Release notes
|
||||
### v3.12 (released 2022-05-27)
|
||||
- Added proper detection of the Sachen 8B-001 mono unlicensed cartridge *(thanks voltagex)*
|
||||
- Fixed an issue with dumping large-size GBA Video cartridges in CLI mode
|
||||
- Added the option to generate ROM dump reports in CLI mode
|
||||
- Minor bug fixes and improvements
|
||||
|
||||
### v3.11 (released 2022-05-25)
|
||||
- Added the option to generate ROM dump reports for game preservation purposes *(thanks Hiccup)*
|
||||
- Bundles GBxCart RW v1.4 firmware version R35+L7 (improves SRAM access on reproduction cartridges and Game Boy Camera access)
|
||||
|
|
|
|||
|
|
@ -127,7 +127,7 @@ def main(portableMode=False):
|
|||
|
||||
ap_cli2 = parser.add_argument_group('optional command line interface arguments')
|
||||
ap_cli2.add_argument("--dmg-romsize", choices=["auto", "32kb", "64kb", "128kb", "256kb", "512kb", "1mb", "2mb", "4mb", "8mb", "16mb", "32mb"], type=str.lower, default="auto", help="set size of Game Boy cartridge ROM data")
|
||||
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", type=str.lower, default="auto", help="set memory bank controller type of Game Boy cartridge")
|
||||
ap_cli2.add_argument("--dmg-savesize", choices=["auto", "4k", "16k", "64k", "256k", "512k", "1m", "eeprom2k", "eeprom4k", "tama5", "4m"], type=str.lower, default="auto", help="set size of Game Boy cartridge save data")
|
||||
ap_cli2.add_argument("--agb-romsize", choices=["auto", "1mb", "2mb", "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", "flash512k", "flash1m", "dacs8m", "sram512k", "sram1m"], type=str.lower, default="auto", help="set type of Game Boy Advance cartridge save data")
|
||||
|
|
@ -138,6 +138,7 @@ def main(portableMode=False):
|
|||
ap_cli2.add_argument("--reversed-sectors", action="store_true", help="use reversed flash sectors if possible")
|
||||
ap_cli2.add_argument("--force-5v", action="store_true", help="force 5V when writing Game Boy flash cartridges")
|
||||
ap_cli2.add_argument("--no-verify-write", action="store_true", help="do not verify written data")
|
||||
ap_cli2.add_argument("--generate-dump-report", action="store_true", help="generate dump reports when making a ROM backup")
|
||||
ap_cli2.add_argument("--save-filename-add-datetime", action="store_true", help="adds a timestamp to the file name of save data backups")
|
||||
ap_cli2.add_argument("--gbcamera-palette", choices=["grayscale", "dmg", "sgb", "cgb1", "cgb2", "cgb3"], type=str.lower, default="grayscale", help="sets the palette of pictures extracted from Game Boy Camera saves")
|
||||
ap_cli2.add_argument("--gbcamera-outfile-format", choices=["png", "bmp", "gif", "jpg"], type=str.lower, default="png", help="sets the file format of saved pictures extracted from Game Boy Camera saves")
|
||||
|
|
|
|||
|
|
@ -264,6 +264,13 @@ class FlashGBX_CLI():
|
|||
pass
|
||||
|
||||
def FinishOperation(self):
|
||||
time_elapsed = None
|
||||
speed = None
|
||||
if "time_start" in self.PROGRESS.PROGRESS and self.PROGRESS.PROGRESS["time_start"] > 0:
|
||||
time_elapsed = time.time() - self.PROGRESS.PROGRESS["time_start"]
|
||||
speed = "{:.2f} KB/s".format((self.CONN.INFO["transferred"] / 1024.0) / time_elapsed)
|
||||
self.PROGRESS.PROGRESS["time_start"] = 0
|
||||
|
||||
if self.CONN.INFO["last_action"] == 4: # Flash ROM
|
||||
self.CONN.INFO["last_action"] = 0
|
||||
if "verified" in self.PROGRESS.PROGRESS and self.PROGRESS.PROGRESS["verified"] == True:
|
||||
|
|
@ -273,6 +280,25 @@ class FlashGBX_CLI():
|
|||
|
||||
elif self.CONN.INFO["last_action"] == 1: # Backup ROM
|
||||
self.CONN.INFO["last_action"] = 0
|
||||
dump_report = False
|
||||
dumpinfo_file = ""
|
||||
if self.ARGS["argparsed"].generate_dump_report is True:
|
||||
try:
|
||||
dump_report = self.CONN.GetDumpReport()
|
||||
if dump_report is not False:
|
||||
if time_elapsed is not None and speed is not None:
|
||||
dump_report = dump_report.replace("%TRANSFER_RATE%", speed)
|
||||
dump_report = dump_report.replace("%TIME_ELAPSED%", Util.formatProgressTime(time_elapsed))
|
||||
else:
|
||||
dump_report = dump_report.replace("%TRANSFER_RATE%", "N/A")
|
||||
dump_report = dump_report.replace("%TIME_ELAPSED%", "N/A")
|
||||
dumpinfo_file = os.path.splitext(self.CONN.INFO["last_path"])[0] + ".txt"
|
||||
with open(dumpinfo_file, "wb") as f:
|
||||
f.write(bytearray([ 0xEF, 0xBB, 0xBF ])) # UTF-8 BOM
|
||||
f.write(dump_report.encode("UTF-8"))
|
||||
except Exception as e:
|
||||
print("ERROR: {:s}".format(str(e)))
|
||||
|
||||
if self.CONN.GetMode() == "DMG":
|
||||
print("CRC32: {:08x}".format(self.CONN.INFO["file_crc32"]))
|
||||
print("SHA-1: {:s}\n".format(self.CONN.INFO["file_sha1"]))
|
||||
|
|
@ -304,7 +330,7 @@ class FlashGBX_CLI():
|
|||
else:
|
||||
msg += "\nThis may indicate a bad dump, however this can be normal for some reproduction cartridges, unlicensed games, prototypes, patched games and intentional overdumps."
|
||||
print("{:s}{:s}{:s}".format(ANSI.YELLOW, msg, ANSI.RESET))
|
||||
|
||||
|
||||
elif self.CONN.INFO["last_action"] == 2: # Backup RAM
|
||||
self.CONN.INFO["last_action"] = 0
|
||||
if not "debug" in self.ARGS and self.CONN.INFO["transferred"] == 131072: # 128 KB
|
||||
|
|
@ -598,7 +624,7 @@ class FlashGBX_CLI():
|
|||
stok = True
|
||||
s += "Save Type: {:s}\n".format(Util.AGB_Header_Save_Types[6])
|
||||
data["save_type"] = 6
|
||||
|
||||
|
||||
if stok is False:
|
||||
s += "Save Type: Not detected\n"
|
||||
|
||||
|
|
@ -732,12 +758,18 @@ class FlashGBX_CLI():
|
|||
print("{:s}Couldn’t determine MBC type, will try to use MBC5. It can also be manually set with the “--dmg-mbc” command line switch.{:s}".format(ANSI.YELLOW, ANSI.RESET))
|
||||
mbc = 0x19
|
||||
else:
|
||||
mbc = int(args.dmg_mbc)
|
||||
if mbc == 2: mbc = 0x06
|
||||
elif mbc == 3: mbc = 0x13
|
||||
elif mbc == 5: mbc = 0x19
|
||||
elif mbc == 6: mbc = 0x20
|
||||
elif mbc == 7: mbc = 0x22
|
||||
if args.dmg_mbc.startswith("0x"):
|
||||
mbc = int(args.dmg_mbc[2:], 16)
|
||||
elif args.dmg_mbc.isnumeric():
|
||||
mbc = int(args.dmg_mbc)
|
||||
if mbc == 2: mbc = 0x06
|
||||
elif mbc == 3: mbc = 0x13
|
||||
elif mbc == 5: mbc = 0x19
|
||||
elif mbc == 6: mbc = 0x20
|
||||
elif mbc == 7: mbc = 0x22
|
||||
else: mbc = 0x19
|
||||
else:
|
||||
mbc = 0x19
|
||||
|
||||
if args.dmg_romsize == "auto":
|
||||
try:
|
||||
|
|
@ -786,7 +818,6 @@ class FlashGBX_CLI():
|
|||
print("Canceled.")
|
||||
return
|
||||
|
||||
|
||||
try:
|
||||
f = open(path, "ab+")
|
||||
f.close()
|
||||
|
|
@ -818,11 +849,25 @@ class FlashGBX_CLI():
|
|||
if not "names" in carts[i]: continue
|
||||
if carts[i]["type"] != self.CONN.GetMode(): continue
|
||||
if args.flashcart_type in carts[i]["names"] and "flash_size" in carts[i]:
|
||||
print("Selected flash cartridge type: {:s}".format(args.flashcart_type))
|
||||
print("Selected cartridge type: {:s}\n".format(args.flashcart_type))
|
||||
rom_size = carts[i]["flash_size"]
|
||||
cart_type = i
|
||||
break
|
||||
|
||||
if cart_type == 0:
|
||||
print("ERROR: Couldn’t select the selected cartridge type.\n")
|
||||
else:
|
||||
if self.CONN.GetMode() == "AGB":
|
||||
cart_types = self.CONN.GetSupportedCartridgesAGB()
|
||||
if "flash_type" in header:
|
||||
print("Selected cartridge type: {:s}\n".format(cart_types[0][i]))
|
||||
cart_type = header["flash_type"]
|
||||
elif header['logo_correct'] and header['3d_memory'] is True:
|
||||
for i in range(0, len(cart_types[0])):
|
||||
if "3d_memory" in cart_types[1][i]:
|
||||
print("Selected cartridge type: {:s}\n".format(cart_types[0][i]))
|
||||
cart_type = i
|
||||
break
|
||||
|
||||
self.CONN.TransferData(args={ 'mode':1, 'path':path, 'mbc':mbc, 'rom_size':rom_size, 'agb_rom_size':rom_size, 'start_addr':0, 'fast_read_mode':True, 'cart_type':cart_type }, signal=self.PROGRESS.SetProgress)
|
||||
|
||||
def FlashROM(self, args, header):
|
||||
|
|
@ -960,12 +1005,18 @@ class FlashGBX_CLI():
|
|||
print("{:s}Couldn’t determine MBC type, will try to use MBC5. It can also be manually set with the “--dmg-mbc” command line switch.{:s}".format(ANSI.YELLOW, ANSI.RESET))
|
||||
mbc = 0x19
|
||||
else:
|
||||
mbc = int(args.dmg_mbc)
|
||||
if mbc == 2: mbc = 0x06
|
||||
elif mbc == 3: mbc = 0x13
|
||||
elif mbc == 5: mbc = 0x19
|
||||
elif mbc == 6: mbc = 0x20
|
||||
elif mbc == 7: mbc = 0x22
|
||||
if args.dmg_mbc.startswith("0x"):
|
||||
mbc = int(args.dmg_mbc[2:], 16)
|
||||
elif args.dmg_mbc.isnumeric():
|
||||
mbc = int(args.dmg_mbc)
|
||||
if mbc == 2: mbc = 0x06
|
||||
elif mbc == 3: mbc = 0x13
|
||||
elif mbc == 5: mbc = 0x19
|
||||
elif mbc == 6: mbc = 0x20
|
||||
elif mbc == 7: mbc = 0x22
|
||||
else: mbc = 0x19
|
||||
else:
|
||||
mbc = 0x19
|
||||
|
||||
if args.dmg_savesize == "auto":
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -225,10 +225,17 @@ class RomFileDMG:
|
|||
data["rom_checksum"] = 0x55E6
|
||||
data["game_title"] = "SACHEN 4B-006"
|
||||
elif sachen_hash == bytearray([ 0xD8, 0x24, 0xD2, 0xB2, 0x71, 0x6B, 0x08, 0xFA, 0xEA, 0xA4, 0xFB, 0xD9, 0x7D, 0x81, 0x94, 0x57, 0x46, 0x77, 0x91, 0x60 ]):
|
||||
data["rom_size_raw"] = 0x03
|
||||
data["mapper_raw"] = 0x204
|
||||
data["rom_checksum"] = 0x8E9F
|
||||
data["game_title"] = "SACHEN 4B-007"
|
||||
sachen_hash2 = hashlib.sha1(buffer[0x0:0x80]).digest()
|
||||
if sachen_hash2 == bytearray([ 0x20, 0x17, 0x3B, 0x95, 0xFB, 0x1A, 0xAC, 0x81, 0x6C, 0x66, 0xF5, 0x62, 0x11, 0xF4, 0x96, 0xFB, 0xFB, 0x88, 0x03, 0xBC ]):
|
||||
data["rom_size_raw"] = 0x04
|
||||
data["mapper_raw"] = 0x204
|
||||
data["rom_checksum"] = 0x657A
|
||||
data["game_title"] = "SACHEN 8B-001"
|
||||
else:
|
||||
data["rom_size_raw"] = 0x03
|
||||
data["mapper_raw"] = 0x204
|
||||
data["rom_checksum"] = 0x8E9F
|
||||
data["game_title"] = "SACHEN 4B-007"
|
||||
elif sachen_hash == bytearray([ 0x19, 0x3E, 0xF8, 0xE2, 0x12, 0x8A, 0x24, 0x10, 0xFE, 0xE9, 0xEA, 0x27, 0xC9, 0x1B, 0xC4, 0xDD, 0x04, 0x74, 0x1B, 0xA8 ]):
|
||||
data["rom_size_raw"] = 0x03
|
||||
data["mapper_raw"] = 0x204
|
||||
|
|
|
|||
|
|
@ -7,7 +7,7 @@ from enum import Enum
|
|||
|
||||
# Common constants
|
||||
APPNAME = "FlashGBX"
|
||||
VERSION_PEP440 = "3.11"
|
||||
VERSION_PEP440 = "3.12"
|
||||
VERSION = "v{:s}".format(VERSION_PEP440)
|
||||
DEBUG = False
|
||||
|
||||
|
|
|
|||
|
|
@ -1990,6 +1990,7 @@ class GbxDevice:
|
|||
# Clean up
|
||||
self.INFO["last_action"] = self.INFO["action"]
|
||||
self.INFO["action"] = None
|
||||
self.INFO["last_path"] = args["path"]
|
||||
self.SetProgress({"action":"FINISHED"})
|
||||
return True
|
||||
|
||||
|
|
|
|||
Binary file not shown.
|
|
@ -336,6 +336,7 @@ The author would like to thank the following very kind people for their help and
|
|||
- Timville (sample cartridge contribution, flash chip info)
|
||||
- twitnic (flash chip info)
|
||||
- Veund (flash chip info)
|
||||
- voltagex (bug reports)
|
||||
- Voultar (bug reports, feature suggestions)
|
||||
- Wkr (flash chip info)
|
||||
- x7l7j8cc (flash chip info)
|
||||
|
|
|
|||
2
setup.py
2
setup.py
|
|
@ -4,7 +4,7 @@ with open("README.md", "r", encoding="utf-8") as fh: long_description = fh.read(
|
|||
|
||||
setuptools.setup(
|
||||
name="FlashGBX",
|
||||
version="3.11",
|
||||
version="3.12",
|
||||
author="Lesserkuma",
|
||||
description="Reads and writes Game Boy and Game Boy Advance cartridge data. Supported hardware: GBxCart RW v1.3 and v1.4 by insideGadgets.",
|
||||
url="https://github.com/lesserkuma/FlashGBX",
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user