From cff844d67b3af8559e7dc59d8ba2e4387dc8d39a Mon Sep 17 00:00:00 2001 From: Lesserkuma Date: Mon, 25 Sep 2023 12:19:31 +0200 Subject: [PATCH] 3.33 --- CHANGES.md | 3 ++ FlashGBX/FlashGBX_CLI.py | 2 +- FlashGBX/FlashGBX_GUI.py | 28 +++++------ FlashGBX/Mapper.py | 9 ++-- FlashGBX/Util.py | 8 ++-- FlashGBX/hw_GBxCartRW.py | 91 ++++++++++++++++++++++-------------- FlashGBX/hw_GBxCartRW_ofw.py | 5 +- README.md | 4 +- setup.py | 2 +- 9 files changed, 90 insertions(+), 62 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 846a430..4c4b77a 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,7 @@ # Release notes +### v3.33 +- Minor bug fixes and improvements *(thanks Eldram, Grender)* + ### v3.32 (released 2023-07-25) - Added support for M5M29-39VF512 with M5M29HD528 *(thanks marv17)* - Added support for SD007_BV5_V3 with 26LV160BTC diff --git a/FlashGBX/FlashGBX_CLI.py b/FlashGBX/FlashGBX_CLI.py index d67d13f..b1b09c0 100644 --- a/FlashGBX/FlashGBX_CLI.py +++ b/FlashGBX/FlashGBX_CLI.py @@ -433,7 +433,7 @@ class FlashGBX_CLI(): def DisconnectDevice(self): try: devname = self.CONN.GetFullNameExtended() - self.CONN.Close() + self.CONN.Close(cartPowerOff=True) print("Disconnected from {:s}".format(devname)) except: pass diff --git a/FlashGBX/FlashGBX_GUI.py b/FlashGBX/FlashGBX_GUI.py index 388b879..ffa4b32 100644 --- a/FlashGBX/FlashGBX_GUI.py +++ b/FlashGBX/FlashGBX_GUI.py @@ -202,7 +202,7 @@ class FlashGBX_GUI(QtWidgets.QWidget): self.mnuConfig.addAction("Check for &updates on application startup", lambda: [ self.EnableUpdateCheck() ]) 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", lambda: self.SETTINGS.setValue("PreferChipErase", str(self.mnuConfig.actions()[2].isChecked()).lower().replace("true", "enabled").replace("false", "disabled"))) - self.mnuConfig.addAction("&Verify written data", lambda: self.SETTINGS.setValue("VerifyData", str(self.mnuConfig.actions()[3].isChecked()).lower().replace("true", "enabled").replace("false", "disabled"))) + self.mnuConfig.addAction("&Verify transferred data", lambda: self.SETTINGS.setValue("VerifyData", str(self.mnuConfig.actions()[3].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.addAction("Limit &baud rate to 1Mbps for GBxCart RW v1.4 devices", lambda: [ self.SETTINGS.setValue("LimitBaudRate", str(self.mnuConfig.actions()[5].isChecked()).lower().replace("true", "enabled").replace("false", "disabled")), self.SetLimitBaudRate() ]) self.mnuConfig.addAction("Always &generate ROM dump reports", lambda: self.SETTINGS.setValue("GenerateDumpReports", str(self.mnuConfig.actions()[6].isChecked()).lower().replace("true", "enabled").replace("false", "disabled"))) @@ -564,7 +564,7 @@ class FlashGBX_GUI(QtWidgets.QWidget): def DisconnectDevice(self): try: devname = self.CONN.GetFullNameExtended() - self.CONN.Close() + self.CONN.Close(cartPowerOff=True) self.CONN = None self.DEVICES = {} print("Disconnected from {:s}".format(devname)) @@ -1085,11 +1085,13 @@ class FlashGBX_GUI(QtWidgets.QWidget): if self.CONN.GetMode() == "AGB" and "Batteryless SRAM" in Util.AGB_Header_Save_Types[self.cmbAGBSaveTypeResult.currentIndex()]: temp1 = self.cmbAGBCartridgeTypeResult.currentIndex() temp2 = self.cmbAGBSaveTypeResult.currentIndex() - temp3 = self.CONN.INFO["dump_info"]["batteryless_sram"] + if "batteryless_sram" in self.CONN.INFO["dump_info"]: + temp3 = self.CONN.INFO["dump_info"]["batteryless_sram"] self.ReadCartridge(resetStatus=False) self.cmbAGBCartridgeTypeResult.setCurrentIndex(temp1) self.cmbAGBSaveTypeResult.setCurrentIndex(temp2) - self.CONN.INFO["dump_info"]["batteryless_sram"] = temp3 + if "batteryless_sram" in self.CONN.INFO["dump_info"]: + self.CONN.INFO["dump_info"]["batteryless_sram"] = temp3 else: self.ReadCartridge(resetStatus=False) @@ -1717,7 +1719,7 @@ class FlashGBX_GUI(QtWidgets.QWidget): self.lblStatus4a.setText("Testing ({:s} 1/2)...".format(test_patterns_names[0])) self.SetProgressBars(min=0, max=len(test_patterns)+3, value=0) qt_app.processEvents() - args = { "mode":2, "path":path, "mbc":mbc, "save_type":save_type, "rtc":rtc } + args = { "mode":2, "path":path, "mbc":mbc, "save_type":save_type, "rtc":False } t = threading.Thread(target=lambda a: self.CONN.TransferData(args=a, signal=None), args=[args]) t.start() while t.is_alive(): @@ -1764,7 +1766,7 @@ class FlashGBX_GUI(QtWidgets.QWidget): self.SetProgressBars(min=0, max=len(test_patterns)+3, value=i+2) qt_app.processEvents() towrite = test_patterns[i] - args = { "mode":3, "path":path, "mbc":mbc, "save_type":save_type, "rtc":rtc, "rtc_advance":rtc_advance, "erase":erase, "verify_write":False, "buffer":towrite } + args = { "mode":3, "path":path, "mbc":mbc, "save_type":save_type, "rtc":False, "rtc_advance":rtc_advance, "erase":erase, "verify_write":False, "buffer":towrite } t = threading.Thread(target=lambda a: self.CONN.TransferData(args=a, signal=None), args=[args]) t.start() while t.is_alive(): @@ -1776,7 +1778,7 @@ class FlashGBX_GUI(QtWidgets.QWidget): self.CONN.CartPowerOff() time.sleep(0.5) self.CONN.CartPowerOn() - args = { "mode":2, "path":path, "mbc":mbc, "save_type":save_type, "rtc":rtc } + args = { "mode":2, "path":path, "mbc":mbc, "save_type":save_type, "rtc":False } t = threading.Thread(target=lambda a: self.CONN.TransferData(args=a, signal=None), args=[args]) t.start() while t.is_alive(): @@ -1791,14 +1793,14 @@ class FlashGBX_GUI(QtWidgets.QWidget): self.lblStatus4a.setText("Restoring original save data...") self.SetProgressBars(min=0, max=len(test_patterns)+3, value=len(test_patterns)+2) qt_app.processEvents() - args = { "mode":3, "path":path, "mbc":mbc, "save_type":save_type, "rtc":rtc, "rtc_advance":rtc_advance, "erase":erase, "verify_write":False, "buffer":save1 } + args = { "mode":3, "path":path, "mbc":mbc, "save_type":save_type, "rtc":False, "rtc_advance":rtc_advance, "erase":erase, "verify_write":False, "buffer":save1 } t = threading.Thread(target=lambda a: self.CONN.TransferData(args=a, signal=None), args=[args]) t.start() while t.is_alive(): qt_app.processEvents() time.sleep(0.02) t.join() - args = { "mode":2, "path":path, "mbc":mbc, "save_type":save_type, "rtc":rtc } + args = { "mode":2, "path":path, "mbc":mbc, "save_type":save_type, "rtc":False } t = threading.Thread(target=lambda a: self.CONN.TransferData(args=a, signal=None), args=[args]) t.start() while t.is_alive(): @@ -1820,8 +1822,8 @@ class FlashGBX_GUI(QtWidgets.QWidget): if test_ok == 0: towrite = save1 readback = save2 - with open("debug_savetest_1.bin", "wb") as f: f.write(towrite[:len(readback)]) - with open("debug_savetest_2.bin", "wb") as f: f.write(readback) + with open(Util.CONFIG_PATH + "/debug_stress_test_1.bin", "wb") as f: f.write(towrite[:len(readback)]) + with open(Util.CONFIG_PATH + "/debug_stress_test_2.bin", "wb") as f: f.write(readback) except: pass if test_ok > 0: @@ -2344,7 +2346,7 @@ class FlashGBX_GUI(QtWidgets.QWidget): try: if save_type is not None and save_type is not False: if self.CONN.GetMode() == "DMG": - self.cmbDMGHeaderSaveTypeResult.setCurrentIndex(save_type) + self.cmbDMGHeaderSaveTypeResult.setCurrentIndex(Util.DMG_Header_RAM_Sizes_Map.index(save_type)) elif self.CONN.GetMode() == "AGB": self.cmbAGBSaveTypeResult.setCurrentIndex(save_type) except: @@ -2392,7 +2394,7 @@ class FlashGBX_GUI(QtWidgets.QWidget): else: if self.CONN.GetMode() == "DMG": try: - temp = "{:s}".format(Util.DMG_Header_RAM_Sizes[save_type]) + temp = "{:s}".format(Util.DMG_Header_RAM_Sizes[Util.DMG_Header_RAM_Sizes_Map.index(save_type)]) except: temp = "Unknown" elif self.CONN.GetMode() == "AGB": diff --git a/FlashGBX/Mapper.py b/FlashGBX/Mapper.py index d98fa2f..c3f1f80 100644 --- a/FlashGBX/Mapper.py +++ b/FlashGBX/Mapper.py @@ -263,6 +263,9 @@ class DMG_MBC3(DMG_MBC): def HasRTC(self): dprint("Checking for RTC") + if self.MBC_ID not in (0x0F, 0x10, 0x110): + dprint("No RTC because mapper value is not used for RTC:", self.MBC_ID) + return False self.EnableRAM(enable=False) self.EnableRAM(enable=True) self.LatchRTC() @@ -271,12 +274,12 @@ class DMG_MBC3(DMG_MBC): for i in range(0x08, 0x0D): self.CLK_TOGGLE_FNCPTR(60) self.CartWrite([ [0x4000, i] ]) - data = self.CartRead(0xA000, 0x800) + data = self.CartRead(0xA880, 0x100) if len(data) == 0: return False if data[0] in (0, 0xFF): continue skipped = False - if data != bytearray([data[0]] * 0x800): - dprint("No RTC because whole bank is not the same value", data[0]) + if data != bytearray([data[0]] * 0x100): + dprint("No RTC because whole bank is not the same value:", data[0]) skipped = True break diff --git a/FlashGBX/Util.py b/FlashGBX/Util.py index 58e0dc7..d135af9 100644 --- a/FlashGBX/Util.py +++ b/FlashGBX/Util.py @@ -7,9 +7,9 @@ from enum import Enum # Common constants APPNAME = "FlashGBX" -VERSION_PEP440 = "3.32" +VERSION_PEP440 = "3.33" VERSION = "v{:s}".format(VERSION_PEP440) -VERSION_TIMESTAMP = 1690298775 +VERSION_TIMESTAMP = 1695636983 DEBUG = False DEBUG_LOG = [] APP_PATH = "" @@ -19,8 +19,8 @@ AGB_Header_ROM_Sizes = [ "64 KiB", "128 KiB", "256 KiB", "512 KiB", "1 MiB", "2 AGB_Header_ROM_Sizes_Map = [ 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000 ] AGB_Header_Save_Types = [ "None", "4K EEPROM (512 Bytes)", "64K EEPROM (8 KiB)", "256K SRAM/FRAM (32 KiB)", "512K FLASH (64 KiB)", "1M FLASH (128 KiB)", "8M DACS (1 MiB)", "Unlicensed 512K SRAM (64 KiB)", "Unlicensed 1M SRAM (128 KiB)", "Unlicensed Batteryless SRAM" ] AGB_Header_Save_Sizes = [ 0, 512, 8192, 32768, 65536, 131072, 1048576, 65536, 131072, 0 ] -AGB_Flash_Save_Chips = { 0xBFD4:"SST 39VF512", 0x1F3D:"Atmel AT29LV512", 0xC21C:"Macronix MX29L512", 0x321B:"Panasonic MN63F805MNP", 0xC209:"Macronix MX29L010", 0x6213:"SANYO LE26FV10N1TS", 0xBF5B:"Unlicensed SST SST49LF080A" } -AGB_Flash_Save_Chips_Sizes = [ 0x10000, 0x10000, 0x10000, 0x10000, 0x20000, 0x20000, 0x20000 ] +AGB_Flash_Save_Chips = { 0xBFD4:"SST 39VF512", 0x1F3D:"Atmel AT29LV512", 0xC21C:"Macronix MX29L512", 0x321B:"Panasonic MN63F805MNP", 0xC209:"Macronix MX29L010", 0x6213:"SANYO LE26FV10N1TS", 0xBF5B:"Unlicensed SST SST49LF080A", 0xFFFF:"Unlicensed 0xFFFF" } +AGB_Flash_Save_Chips_Sizes = [ 0x10000, 0x10000, 0x10000, 0x10000, 0x20000, 0x20000, 0x20000, 0x20000 ] DMG_Header_Mapper = { 0x00:'None', 0x01:'MBC1', 0x02:'MBC1+SRAM', 0x03:'MBC1+SRAM+BATTERY', 0x06:'MBC2+SRAM+BATTERY', 0x0F:'MBC3+RTC+BATTERY', 0x10:'MBC3+RTC+SRAM+BATTERY', 0x110:'MBC30+RTC+SRAM+BATTERY', 0x12:'MBC3+SRAM', 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:'MAC-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', 0x203:'Unlicensed Xploder GB Mapper', 0x204:'Unlicensed Sachen Mapper', 0x205:'Unlicensed Datel Orbit V2 Mapper' } DMG_Mapper_Types = { "None":[ 0x00, 0x08, 0x09 ], "MBC1":[ 0x01, 0x02, 0x03 ], "MBC2":[ 0x05, 0x06 ], "MBC3":[ 0x0F, 0x10, 0x11, 0x12, 0x13 ], "MBC30":[ 0x110 ], "MBC5":[ 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E ], "MBC6":[ 0x20 ], "MBC7":[ 0x22 ], "MBC1M":[ 0x101, 0x103 ], "MMM01":[ 0x0B, 0x0D ], "MAC-GBD":[ 0xFC ], "G-MMC1":[ 0x105 ], "M161":[ 0x104 ], "HuC-1":[ 0xFF ], "HuC-3":[ 0xFE ], "TAMA5":[ 0xFD ], "Unlicensed 256M Multi Cart Mapper":[ 0x201 ], "Unlicensed Wisdom Tree Mapper":[ 0x202 ], "Unlicensed Xploder GB Mapper":[ 0x203 ], "Unlicensed Sachen Mapper":[ 0x204 ], "Unlicensed Datel Orbit V2 Mapper":[ 0x205 ] } diff --git a/FlashGBX/hw_GBxCartRW.py b/FlashGBX/hw_GBxCartRW.py index c33aa22..1665791 100644 --- a/FlashGBX/hw_GBxCartRW.py +++ b/FlashGBX/hw_GBxCartRW.py @@ -154,6 +154,7 @@ class GbxDevice: continue elif max_baud >= 1700000 and self.FW["pcb_ver"] in (5, 6, 101) and self.BAUDRATE < 1700000: self.ChangeBaudRate(baudrate=1700000) + self.DEVICE.close() dev = serial.Serial(ports[i], self.BAUDRATE, timeout=0.1) self.DEVICE = dev @@ -250,12 +251,9 @@ class GbxDevice: if not self.IsConnected(): return if baudrate == 1700000: self._write(self.DEVICE_CMD["OFW_USART_1_7M_SPEED"]) - self.Close() - self.BAUDRATE = baudrate elif baudrate == 1000000: self._write(self.DEVICE_CMD["OFW_USART_1_0M_SPEED"]) - self.Close() - self.BAUDRATE = baudrate + self.BAUDRATE = baudrate def CanSetVoltageManually(self): return False @@ -316,14 +314,15 @@ class GbxDevice: print(str(e)) return False - def Close(self): + def Close(self, cartPowerOff=False): if self.IsConnected(): try: - if self.FW["pcb_ver"] in (5, 6, 101): - self._write(self.DEVICE_CMD["OFW_CART_MODE"]) - self._read(1) - self._write(self.DEVICE_CMD["OFW_CART_PWR_OFF"]) - self._write(self.DEVICE_CMD["SET_ADDR_AS_INPUTS"]) + if cartPowerOff: + if self.FW["pcb_ver"] in (5, 6, 101): + self._write(self.DEVICE_CMD["OFW_CART_MODE"]) + self._read(1) + self._write(self.DEVICE_CMD["OFW_CART_PWR_OFF"]) + self._write(self.DEVICE_CMD["SET_ADDR_AS_INPUTS"]) self.DEVICE.close() except: self.DEVICE = None @@ -445,7 +444,7 @@ class GbxDevice: # On MacOS it’s possible not all bytes are transmitted successfully, # even though we’re using flush() which is the tcdrain function. # Still looking for a better solution than delaying here. - if platform.system() == "Darwin": # or self.WRITE_DELAY is True: + if platform.system() == "Darwin" or self.WRITE_DELAY is True: time.sleep(0.00125) if wait: return self.wait_for_ack() @@ -624,7 +623,7 @@ class GbxDevice: return self.MODE def SetMode(self, mode, delay=0.1): - self.CartPowerOff(delay=delay) + # self.CartPowerOff(delay=delay) if mode == "DMG": self._write(self.DEVICE_CMD["SET_MODE_DMG"]) self._write(self.DEVICE_CMD["SET_VOLTAGE_5V"]) @@ -866,45 +865,60 @@ class GbxDevice: # Save Type and Size if checkSaveType: if self.MODE == "DMG": - save_type = 5 + save_size = 131072 + save_type = 0x04 if mbc == 0x20: # MBC6 save_size = 1081344 - save_type = 6 + save_type = 0x104 return (info, save_size, save_type, save_chip, sram_unstable, cart_types, cart_type_id, cfi_s, cfi, flash_id) elif mbc == 0x22: # MBC7 - save_type = 8 + save_type = 0x102 save_size = 512 elif mbc == 0xFD: # TAMA5 save_size = 32 - save_type = 9 + save_type = 0x103 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':save_type, 'rtc':False } elif self.MODE == "AGB": args = { 'mode':2, 'path':None, 'mbc':mbc, 'save_type':8, 'rtc':False } ret = self._BackupRestoreRAM(args=args) - + if ret is not False and "data" in self.INFO: save_size = Util.find_size(self.INFO["data"], len(self.INFO["data"])) else: save_size = 0 - + try: + save_type = Util.DMG_Header_RAM_Sizes_Map[Util.DMG_Header_RAM_Sizes_Flasher_Map.index(save_size)] + except: + save_size = 0 + save_type = 0 + if self.MODE == "DMG": if save_size > 0x20: - if save_size in Util.DMG_Header_RAM_Sizes_Flasher_Map: - save_type = Util.DMG_Header_RAM_Sizes_Flasher_Map.index(save_size) - if mbc == 0x22: # MBC7 - if save_size == 256: - save_type = 7 - elif save_size == 512: - save_type = 8 - elif len(self.INFO["data"]) >= 0x12000 and self.INFO["data"][0x12000:0x14000] == bytearray([self.INFO["data"][0x12000]] * 0x2000): - if self.INFO["data"][0x8000:0x10000] == bytearray([self.INFO["data"][0x8000]] * 0x8000): - save_size = 32768 - save_type = 3 - else: + if mbc == 0x22: # MBC7 + if save_size == 256: + save_type = 0x101 + elif save_size == 512: + save_type = 0x102 + elif save_size > 0x10000: # MBC30+RTC? + check = True + for i in range(0x8000, 0x10000, 0x40): + if self.INFO["data"][i:i+3] != bytearray([self.INFO["data"][i]] * 3): + check = False + break + if check: + save_size = 32768 + save_type = 0x03 + else: + check = True + for i in range(0x1A000, 0x20000, 0x40): + if self.INFO["data"][i:i+3] != bytearray([self.INFO["data"][i]] * 3): + check = False + break + if check: save_size = 65536 - save_type = 4 + save_type = 0x05 elif self.MODE == "AGB": # Check for FLASH @@ -2076,7 +2090,6 @@ class GbxDevice: buffer_len = 0x4000 - self.INFO["dump_info"] = {} self.INFO["dump_info"]["timestamp"] = datetime.datetime.now().astimezone().replace(microsecond=0).isoformat() self.INFO["dump_info"]["file_name"] = args["path"] self.INFO["dump_info"]["file_size"] = args["rom_size"] @@ -2449,7 +2462,10 @@ class GbxDevice: msg = "This cartridge uses a mapper that is not supported by {:s} using your {:s} device. An updated hardware revision is required.".format(Util.APPNAME, self.GetFullName()) self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":msg, "abortable":False}) return False - save_size = Util.DMG_Header_RAM_Sizes_Flasher_Map[Util.DMG_Header_RAM_Sizes_Map.index(args["save_type"])] + if "save_size" in args: + save_size = args["save_size"] + else: + save_size = Util.DMG_Header_RAM_Sizes_Flasher_Map[Util.DMG_Header_RAM_Sizes_Map.index(args["save_type"])] ram_banks = _mbc.GetRAMBanks(save_size) buffer_len = min(0x200, _mbc.GetRAMBankSize()) self._write(self.DEVICE_CMD["SET_MODE_DMG"]) @@ -2522,7 +2538,10 @@ class GbxDevice: self._write(self.DEVICE_CMD["SET_MODE_AGB"]) self._write(self.DEVICE_CMD["SET_VOLTAGE_3_3V"]) buffer_len = 0x2000 - save_size = Util.AGB_Header_Save_Sizes[args["save_type"]] + if "save_size" in args: + save_size = args["save_size"] + else: + save_size = Util.AGB_Header_Save_Sizes[args["save_type"]] ram_banks = math.ceil(save_size / 0x10000) agb_flash_chip = 0 @@ -2539,7 +2558,7 @@ class GbxDevice: return False buffer_len = 0x1000 (agb_flash_chip, _) = ret - if agb_flash_chip == 0xBF5B: # Bootlegs + if agb_flash_chip in (0xBF5B, 0xFFFF): # Bootlegs buffer_len = 0x800 elif args["save_type"] == 6: # DACS self._write(self.DEVICE_CMD["AGB_BOOTUP_SEQUENCE"], wait=True) @@ -2661,7 +2680,7 @@ class GbxDevice: end_address = min(save_size, bank_size) if save_size > bank_size: - if args["save_type"] == 8 or agb_flash_chip == 0xBF5B: # Bootleg 1M + if args["save_type"] == 8 or agb_flash_chip in (0xBF5B, 0xFFFF): # Bootleg 1M dprint("Switching to bootleg save bank {:d}".format(bank)) self._cart_write(0x1000000, bank) elif args["save_type"] == 5: # FLASH 1M diff --git a/FlashGBX/hw_GBxCartRW_ofw.py b/FlashGBX/hw_GBxCartRW_ofw.py index 1eb1b3f..0fc2fbc 100644 --- a/FlashGBX/hw_GBxCartRW_ofw.py +++ b/FlashGBX/hw_GBxCartRW_ofw.py @@ -253,10 +253,11 @@ class GbxDevice: except SerialException: return False - def Close(self): + def Close(self, cartPowerOff=False): if self.IsConnected(): try: - self.set_mode(self.DEVICE_CMD["SET_PINS_AS_INPUTS"]) + if cartPowerOff: + self.set_mode(self.DEVICE_CMD["SET_PINS_AS_INPUTS"]) self.DEVICE.close() except: self.DEVICE = None diff --git a/README.md b/README.md index b0b1321..7553050 100644 --- a/README.md +++ b/README.md @@ -73,7 +73,7 @@ Use this command in a Terminal or Command Prompt window to launch the installed - MBC1M - MMM01 - MAC-GBD (Game Boy Camera) - - G-MMC1 (GB Memory) + - G-MMC1 (GB-Memory Cartridge) - M161 - HuC-1 - HuC-3 @@ -318,7 +318,7 @@ Many different reproduction cartridges share their flash chip command set, so ev The author would like to thank the following very kind people for their help, contributions or documentation (in alphabetical order): -2358, 90sFlav, AcoVanConis, AdmirtheSableye, AlexiG, ALXCO-Hardware, AndehX, antPL, bbsan, BennVenn, ccs21, ClassicOldSong, CodyWick13, Corborg, Cristóbal, crizzlycruz, Crystal, Därk, Davidish, DevDavisNunez, Diddy_Kong, djedditt, Dr-InSide, dyf2007, easthighNerd, EchelonPrime, edo999, Ell, EmperorOfTigers, endrift, Erba Verde, ethanstrax, eveningmoose, Falknör, FerrantePescara, frarees, Frost Clock, gboh, gekkio, Godan, Grender, HDR, Herax, Hiccup, hiks, howie0210, iamevn, Icesythe7, ide, Jayro, Jenetrix, JFox, joyrider3774, JS7457, julgr, Kaede, kane159, KOOORAY, kscheel, kyokohunter, Leitplanke, litlemoran, LovelyA72, Luca DS, LucentW, manuelcm1, marv17, Merkin, metroid-maniac, Mr_V, olDirdey, orangeglo, paarongiroux, Paradoxical, Rairch, Raphaël BOICHOT, redalchemy, RetroGorek, RevZ, s1cp, Satumox, Sgt.DoudouMiel, SH, Shinichi999, Sillyhatday, Sithdown, skite2001, Smelly-Ghost, Stitch, Super Maker, t5b6_de, Tauwasser, Timville, twitnic, velipso, Veund, voltagex, Voultar, wickawack, Wkr, x7l7j8cc, xactoes, yosoo, Zeii, Zelante, zipplet, Zoo, zvxr +2358, 90sFlav, AcoVanConis, AdmirtheSableye, AlexiG, ALXCO-Hardware, AndehX, antPL, bbsan, BennVenn, ccs21, ClassicOldSong, CodyWick13, Corborg, Cristóbal, crizzlycruz, Crystal, Därk, Davidish, DevDavisNunez, Diddy_Kong, djedditt, Dr-InSide, dyf2007, easthighNerd, EchelonPrime, edo999, Eldram, Ell, EmperorOfTigers, endrift, Erba Verde, ethanstrax, eveningmoose, Falknör, FerrantePescara, frarees, Frost Clock, gboh, gekkio, Godan, Grender, HDR, Herax, Hiccup, hiks, howie0210, iamevn, Icesythe7, ide, Jayro, Jenetrix, JFox, joyrider3774, JS7457, julgr, Kaede, kane159, KOOORAY, kscheel, kyokohunter, Leitplanke, litlemoran, LovelyA72, Luca DS, LucentW, manuelcm1, marv17, Merkin, metroid-maniac, Mr_V, olDirdey, orangeglo, paarongiroux, Paradoxical, Rairch, Raphaël BOICHOT, redalchemy, RetroGorek, RevZ, s1cp, Satumox, Sgt.DoudouMiel, SH, Shinichi999, Sillyhatday, Sithdown, skite2001, Smelly-Ghost, Stitch, Super Maker, t5b6_de, Tauwasser, Timville, twitnic, velipso, Veund, voltagex, Voultar, wickawack, Wkr, x7l7j8cc, xactoes, yosoo, Zeii, Zelante, zipplet, Zoo, zvxr ## DISCLAIMER diff --git a/setup.py b/setup.py index 00b377b..f6bf2e7 100644 --- a/setup.py +++ b/setup.py @@ -8,7 +8,7 @@ with open("README.md", "r", encoding="utf-8") as fh: long_description = fh.read( setuptools.setup( name="FlashGBX", - version="3.32", + version="3.33", author="Lesserkuma", description="Reads and writes Game Boy and Game Boy Advance cartridge data using the GBxCart RW by insideGadgets", url="https://github.com/lesserkuma/FlashGBX",