diff --git a/CHANGES.md b/CHANGES.md index fd80833..8e96838 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,9 @@ # Release notes +### v3.9 (released 2022-04-29) +- Added support for Ferrante Crafts cart 64 KB *(thanks FerrantePescara)* +- Added support for Ferrante Crafts cart 512 KB *(thanks FerrantePescara)* +- Fixed a bug with querying MBC3/MBC30 Real Time Clock values *(thanks HDR and AdmirtheSableye)* + ### v3.8 (released 2022-04-21) - Added support for AGB-E05-01 with MSP55LV100G *(thanks EmperorOfTigers)* - Added support for DV15 with MSP55LV100G *(thanks zvxr)* diff --git a/FlashGBX/FlashGBX.py b/FlashGBX/FlashGBX.py index c4f6512..3ea433b 100644 --- a/FlashGBX/FlashGBX.py +++ b/FlashGBX/FlashGBX.py @@ -33,7 +33,7 @@ def LoadConfig(args): (config_version, fc_files) = ReadConfigFiles(args=args) if config_version != Util.VERSION: # Rename old files that have since been replaced/renamed/merged - deprecated_files = [ "fc_AGB_TEST.txt", "fc_DMG_TEST.txt", "fc_AGB_Nintendo_E201850.txt", "fc_AGB_Nintendo_E201868.txt", "config.ini", "fc_DMG_MX29LV320ABTC.txt", "fc_DMG_iG_4MB_MBC3_RTC.txt", "fc_AGB_Flash2Advance.txt", "fc_AGB_MX29LV640_AUDIO.txt", "fc_AGB_M36L0R7050T.txt", "fc_AGB_M36L0R8060B.txt", "fc_AGB_M36L0R8060T.txt", "fc_AGB_iG_32MB_S29GL512N.txt" ] + deprecated_files = [ "fc_AGB_TEST.txt", "fc_DMG_TEST.txt", "fc_AGB_Nintendo_E201850.txt", "fc_AGB_Nintendo_E201868.txt", "config.ini", "fc_DMG_MX29LV320ABTC.txt", "fc_DMG_iG_4MB_MBC3_RTC.txt", "fc_AGB_Flash2Advance.txt", "fc_AGB_MX29LV640_AUDIO.txt", "fc_AGB_M36L0R7050T.txt", "fc_AGB_M36L0R8060B.txt", "fc_AGB_M36L0R8060T.txt", "fc_AGB_iG_32MB_S29GL512N.txt", "fc_DMG_SST39SF010_AUDIO.txt" ] for file in deprecated_files: if os.path.exists(config_path + "/" + file): os.rename(config_path + "/" + file, config_path + "/" + file + "_" + datetime.datetime.now().strftime("%Y%m%d%H%M%S") + ".bak") @@ -59,17 +59,18 @@ def LoadConfig(args): # Read flash cart types for file in fc_files: - with open(file, encoding='utf-8') as f: - data = f.read() - specs_int = re.sub("(0x[0-9A-F]+)", lambda m: str(int(m.group(1), 16)), data) # hex numbers to int numbers, otherwise not valid json - try: - specs = json.loads(specs_int) - except: - ret.append([2, "The flashchip type file “{:s}” could not be parsed and needs to be fixed before it can be used.".format(os.path.basename(file))]) - continue - for name in specs["names"]: - if not specs["type"] in flashcarts: continue # only DMG and AGB are supported right now - flashcarts[specs["type"]][name] = specs + if os.path.exists(file): + with open(file, encoding='utf-8') as f: + data = f.read() + specs_int = re.sub("(0x[0-9A-F]+)", lambda m: str(int(m.group(1), 16)), data) # hex numbers to int numbers, otherwise not valid json + try: + specs = json.loads(specs_int) + except: + ret.append([2, "The flashchip type file “{:s}” could not be parsed and needs to be fixed before it can be used.".format(os.path.basename(file))]) + continue + for name in specs["names"]: + if not specs["type"] in flashcarts: continue # only DMG and AGB are supported right now + flashcarts[specs["type"]][name] = specs return { "flashcarts":flashcarts, "config_ret":ret } diff --git a/FlashGBX/Util.py b/FlashGBX/Util.py index 684a452..265394c 100644 --- a/FlashGBX/Util.py +++ b/FlashGBX/Util.py @@ -7,7 +7,7 @@ from enum import Enum # Common constants APPNAME = "FlashGBX" -VERSION_PEP440 = "3.8" +VERSION_PEP440 = "3.9" VERSION = "v{:s}".format(VERSION_PEP440) DEBUG = False diff --git a/FlashGBX/config/fc_DMG_AT49F040_WR.txt b/FlashGBX/config/fc_DMG_AT49F040_WR.txt index 1d900db..98863c4 100644 --- a/FlashGBX/config/fc_DMG_AT49F040_WR.txt +++ b/FlashGBX/config/fc_DMG_AT49F040_WR.txt @@ -24,9 +24,6 @@ [ 0x2AAA, 0x55 ], [ 0x5555, 0x90 ] ], - "read_cfi":[ - [ 0x5555, 0x98 ] - ], "chip_erase":[ [ 0x5555, 0xAA ], [ 0x2AAA, 0x55 ], diff --git a/FlashGBX/config/fc_DMG_FerranteCrafts_32KB.txt b/FlashGBX/config/fc_DMG_FerranteCrafts_32KB.txt new file mode 100644 index 0000000..43ea70d --- /dev/null +++ b/FlashGBX/config/fc_DMG_FerranteCrafts_32KB.txt @@ -0,0 +1,54 @@ +{ + "type":"DMG", + "names":[ + "Ferrante Crafts cart 32 KB" + ], + "flash_ids":[ + [ 0xBF, 0xB5, 0x01, 0xFF ] + ], + "voltage":5, + "flash_size":0x8000, + "start_addr":0, + "first_bank":1, + "write_pin":"AUDIO", + "chip_erase_timeout":20, + "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 ] + ] + } +} diff --git a/FlashGBX/config/fc_DMG_FerranteCrafts_64KB.txt b/FlashGBX/config/fc_DMG_FerranteCrafts_64KB.txt new file mode 100644 index 0000000..bf2a1db --- /dev/null +++ b/FlashGBX/config/fc_DMG_FerranteCrafts_64KB.txt @@ -0,0 +1,55 @@ +{ + "type":"DMG", + "names":[ + "Ferrante Crafts cart 64 KB" + ], + "flash_ids":[ + [ 0xBF, 0xB5, 0x01, 0xFF ] + ], + "voltage":5, + "flash_size":0x10000, + "start_addr":0, + "first_bank":1, + "flash_commands_on_bank_1":true, + "write_pin":"AUDIO", + "chip_erase_timeout":20, + "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 ] + ] + } +} diff --git a/FlashGBX/config/fc_DMG_MX29GL256EL.txt b/FlashGBX/config/fc_DMG_MX29GL256EL.txt index 9fd9265..003a418 100644 --- a/FlashGBX/config/fc_DMG_MX29GL256EL.txt +++ b/FlashGBX/config/fc_DMG_MX29GL256EL.txt @@ -1,8 +1,7 @@ { "type":"DMG", "names":[ - "SD008-6810-V4 with MX29GL256EL", - "SD008-6810-V4 with unlabeled flash chip" + "SD008-6810-V4 with MX29GL256EL" ], "flash_ids":[ [ 0xF3, 0xC3, 0x00, 0x01 ], diff --git a/FlashGBX/config/fc_DMG_SST39SF010_AUDIO.txt b/FlashGBX/config/fc_DMG_SST39SF020_MBC1_AUDIO.txt similarity index 84% rename from FlashGBX/config/fc_DMG_SST39SF010_AUDIO.txt rename to FlashGBX/config/fc_DMG_SST39SF020_MBC1_AUDIO.txt index 7b57b33..82b58c0 100644 --- a/FlashGBX/config/fc_DMG_SST39SF010_AUDIO.txt +++ b/FlashGBX/config/fc_DMG_SST39SF020_MBC1_AUDIO.txt @@ -1,19 +1,19 @@ { "type":"DMG", "names":[ - "Ferrante Crafts cart with SST39SF010A", "GB-CART32K-A with SST39SF020A" ], "flash_ids":[ - [ 0xBF, 0xB5, 0x01, 0xFF ], [ 0xBF, 0xB6, 0x01, 0xFF ] ], "voltage":5, - "flash_size":0x8000, + "flash_size":0x10000, "start_addr":0, "first_bank":1, + "mbc":0x03, + "flash_commands_on_bank_1":true, "write_pin":"AUDIO", - "chip_erase_timeout":60, + "chip_erase_timeout":20, "command_set":"AMD", "commands":{ "reset":[ @@ -24,9 +24,6 @@ [ 0x2AAA, 0x55 ], [ 0x5555, 0x90 ] ], - "read_cfi":[ - [ 0x5555, 0x98 ] - ], "chip_erase":[ [ 0x5555, 0xAA ], [ 0x2AAA, 0x55 ], diff --git a/FlashGBX/config/fc_DMG_SST39SF040_MBC1_AUDIO.txt b/FlashGBX/config/fc_DMG_SST39SF040_MBC1_AUDIO.txt index 3858d6b..dc8eae1 100644 --- a/FlashGBX/config/fc_DMG_SST39SF040_MBC1_AUDIO.txt +++ b/FlashGBX/config/fc_DMG_SST39SF040_MBC1_AUDIO.txt @@ -10,6 +10,7 @@ "flash_size":0x80000, "start_addr":0, "first_bank":1, + "mbc":0x03, "flash_commands_on_bank_1":true, "write_pin":"AUDIO", "chip_erase_timeout":30, diff --git a/FlashGBX/config/fc_DMG_SST39SF040_MBC5_AUDIO.txt b/FlashGBX/config/fc_DMG_SST39SF040_MBC5_AUDIO.txt new file mode 100644 index 0000000..010be6c --- /dev/null +++ b/FlashGBX/config/fc_DMG_SST39SF040_MBC5_AUDIO.txt @@ -0,0 +1,56 @@ +{ + "type":"DMG", + "names":[ + "Ferrante Crafts cart 512 KB" + ], + "flash_ids":[ + [ 0xBF, 0xB7, 0x01, 0xFF ] + ], + "voltage":5, + "flash_size":0x80000, + "start_addr":0, + "first_bank":1, + "mbc":0x19, + "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 ] + ] + } +} diff --git a/FlashGBX/config/fc_DMG_TC58FVB016FT.txt b/FlashGBX/config/fc_DMG_TC58FVB016FT.txt index b74e547..42327f0 100644 --- a/FlashGBX/config/fc_DMG_TC58FVB016FT.txt +++ b/FlashGBX/config/fc_DMG_TC58FVB016FT.txt @@ -3,7 +3,10 @@ "names":[ "SD007_T40_64BALL_TSOP28 with TC58FVB016FT-85" ], - "voltage":3.3, + "flash_ids":[ + [ 0x98, 0x45, 0x00, 0x2A ] + ], + "voltage":5, "flash_size":0x200000, "start_addr":0, "first_bank":1, diff --git a/FlashGBX/config/fc_DMG_iG_512KB.txt b/FlashGBX/config/fc_DMG_iG_512KB.txt index ec8ab7f..0122fc0 100644 --- a/FlashGBX/config/fc_DMG_iG_512KB.txt +++ b/FlashGBX/config/fc_DMG_iG_512KB.txt @@ -10,7 +10,6 @@ ], "voltage":5, "power_cycle":true, - "flash_size":0x80000, "start_addr":0, "first_bank":1, "flash_commands_on_bank_1":true, diff --git a/FlashGBX/fw_GBxCartRW_v1_3.py b/FlashGBX/fw_GBxCartRW_v1_3.py index 3cbc200..2f71627 100644 --- a/FlashGBX/fw_GBxCartRW_v1_3.py +++ b/FlashGBX/fw_GBxCartRW_v1_3.py @@ -193,10 +193,10 @@ class FirmwareUpdaterWindow(QtWidgets.QDialog): fw = "" path = "" if self.optCFW.isChecked(): - fw = "Version {:s}".format(self.CFW_VER) + fw = self.CFW_VER fn = "cfw.hex" elif self.optOFW.isChecked(): - fw = "Version {:s}".format(self.OFW_VER) + fw = self.OFW_VER fn = "ofw.hex" else: path = self.APP.SETTINGS.value("LastDirFirmwareUpdate") @@ -298,7 +298,7 @@ class FirmwareUpdaterWindow(QtWidgets.QDialog): if self.ResetAVR(delay) is False: fncSetStatus(text="Status: Bootloader error.", enableUI=True) self.prgStatus.setValue(0) - msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Critical, windowTitle="FlashGBX", text="The firmware update was not successful as the GBxCart RW bootloader is not responding. If it doesn’t work even after multiple retries, please use the official firmware updater instead.", standardButtons=QtWidgets.QMessageBox.Ok) + msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Critical, windowTitle="FlashGBX", text="The firmware update failed as the device is not responding correctly. Please ensure you use a genuine GBxCart RW, re-connect using a different USB cable and try again.\n\n⚠️ For safety reasons and to avoid potential fire hazards, do not use unauthorized clone hardware that have no electrical fuses, such as the “FLASH BOY” series.".replace("\n", "
"), standardButtons=QtWidgets.QMessageBox.Ok) answer = msgbox.exec() return 2 diff --git a/FlashGBX/fw_GBxCartRW_v1_4.py b/FlashGBX/fw_GBxCartRW_v1_4.py index abcc3cc..3c1a05b 100644 --- a/FlashGBX/fw_GBxCartRW_v1_4.py +++ b/FlashGBX/fw_GBxCartRW_v1_4.py @@ -109,7 +109,7 @@ class FirmwareUpdaterWindow(QtWidgets.QDialog): self.DEVICE = device else: self.APP.QT_APP.processEvents() - text = "This Firmware Updater is for insideGadgets GBxCart RW v1.4 devices only. Please only proceed if your device matches this hardware revision.\n\nGBxCart RW v1.3 can be updated only after connecting to it first. If you want to update another GBxCart RW hardware revision, please use the official firmware updater by insideGadgets instead." + text = "This Firmware Updater is for insideGadgets GBxCart RW v1.4 devices only. Please only proceed if your device matches this hardware revision.\n\nOlder GBxCart RW revisions can be updated only after connecting to them first." msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Warning, windowTitle="FlashGBX", text=text, standardButtons=QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel) msgbox.setDefaultButton(QtWidgets.QMessageBox.Ok) answer = msgbox.exec() diff --git a/FlashGBX/hw_GBxCartRW.py b/FlashGBX/hw_GBxCartRW.py index b61d5e5..8f93d29 100644 --- a/FlashGBX/hw_GBxCartRW.py +++ b/FlashGBX/hw_GBxCartRW.py @@ -895,7 +895,7 @@ class GbxDevice: return buffer - def ReadROM_3DMemory(self, address, length, max_length=512): + def ReadROM_3DMemory(self, address, length, max_length=64): buffer_size = 0x1000 num = math.ceil(length / max_length) dprint("Reading 0x{:X} bytes from cartridge ROM in {:d} iteration(s)".format(length, num)) @@ -920,7 +920,7 @@ class GbxDevice: return buffer - def ReadRAM(self, address, length, command=None, max_length=512): + def ReadRAM(self, address, length, command=None, max_length=64): num = math.ceil(length / max_length) dprint("Reading 0x{:X} bytes from cartridge RAM in {:d} iteration(s)".format(length, num)) if length > max_length: length = max_length @@ -1414,6 +1414,8 @@ class GbxDevice: flashcart.Reset(full_reset=False) dprint("Found the correct cartridge type!") + if self.CanPowerCycleCart(): self.CartPowerCycle() + # Check flash size flash_type_id = 0 cfi_s = "" @@ -1426,19 +1428,20 @@ class GbxDevice: supp_flash_types = self.GetSupportedCartridgesAGB() (flash_id, cfi_s, cfi) = self.CheckFlashChip(limitVoltage=limitVoltage, cart_type=supp_flash_types[1][flash_type_id]) - size = supp_flash_types[1][flash_types[0]]["flash_size"] - size_undetected = False - for i in range(0, len(flash_types)): - if size != supp_flash_types[1][flash_types[i]]["flash_size"]: - size_undetected = True - - if size_undetected: - if isinstance(cfi, dict) and "device_size" in cfi: - for i in range(0, len(flash_types)): - if cfi['device_size'] == supp_flash_types[1][flash_types[i]]["flash_size"]: - flash_type_id = flash_types[i] - size_undetected = False - break + if "flash_size" in supp_flash_types[1][flash_types[0]]: + size = supp_flash_types[1][flash_types[0]]["flash_size"] + size_undetected = False + for i in range(0, len(flash_types)): + if size != supp_flash_types[1][flash_types[i]]["flash_size"]: + size_undetected = True + + if size_undetected: + if isinstance(cfi, dict) and "device_size" in cfi: + for i in range(0, len(flash_types)): + if cfi['device_size'] == supp_flash_types[1][flash_types[i]]["flash_size"]: + flash_type_id = flash_types[i] + size_undetected = False + break else: (flash_id, cfi_s, cfi) = self.CheckFlashChip(limitVoltage=limitVoltage) diff --git a/FlashGBX/hw_GBxCartRW_ofw.py b/FlashGBX/hw_GBxCartRW_ofw.py index cda2270..3fbd4d5 100644 --- a/FlashGBX/hw_GBxCartRW_ofw.py +++ b/FlashGBX/hw_GBxCartRW_ofw.py @@ -903,19 +903,20 @@ class GbxDevice: supp_flash_types = self.GetSupportedCartridgesAGB() (flash_id, cfi_s, cfi) = self.CheckFlashChip(limitVoltage=limitVoltage, cart_type=supp_flash_types[1][flash_type_id]) - size = supp_flash_types[1][flash_types[0]]["flash_size"] - size_undetected = False - for i in range(0, len(flash_types)): - if size != supp_flash_types[1][flash_types[i]]["flash_size"]: - size_undetected = True - - if size_undetected: - if isinstance(cfi, dict) and "device_size" in cfi: - for i in range(0, len(flash_types)): - if cfi['device_size'] == supp_flash_types[1][flash_types[i]]["flash_size"]: - flash_type_id = flash_types[i] - size_undetected = False - break + if "flash_size" in supp_flash_types[1][flash_types[0]]: + size = supp_flash_types[1][flash_types[0]]["flash_size"] + size_undetected = False + for i in range(0, len(flash_types)): + if size != supp_flash_types[1][flash_types[i]]["flash_size"]: + size_undetected = True + + if size_undetected: + if isinstance(cfi, dict) and "device_size" in cfi: + for i in range(0, len(flash_types)): + if cfi['device_size'] == supp_flash_types[1][flash_types[i]]["flash_size"]: + flash_type_id = flash_types[i] + size_undetected = False + break else: (flash_id, cfi_s, cfi) = self.CheckFlashChip(limitVoltage=limitVoltage) diff --git a/FlashGBX/res/config.zip b/FlashGBX/res/config.zip index 53c0b14..1bfab2e 100644 Binary files a/FlashGBX/res/config.zip and b/FlashGBX/res/config.zip differ diff --git a/FlashGBX/res/fw_GBxCart_RW_v1_3.zip b/FlashGBX/res/fw_GBxCart_RW_v1_3.zip index 53f0126..69e9e83 100644 Binary files a/FlashGBX/res/fw_GBxCart_RW_v1_3.zip and b/FlashGBX/res/fw_GBxCart_RW_v1_3.zip differ diff --git a/README.md b/README.md index 7873578..b33aaef 100644 --- a/README.md +++ b/README.md @@ -98,7 +98,9 @@ Use this command in a Terminal or Command Prompt window to launch the installed - DIY cart with MX29LV640 - DIY cart with SST39SF040 - DMG-MBC5-32M-FLASH Development Cartridge, E201264 - - Ferrante Crafts cart with SST39SF010A + - Ferrante Crafts cart 32 KB + - Ferrante Crafts cart 64 KB + - Ferrante Crafts cart 512 KB - GB-CART32K-A with SST39SF020A - GB Smart 32M - HDR Game Boy Camera Flashcart @@ -237,7 +239,7 @@ Use this command in a Terminal or Command Prompt window to launch the installed Many different reproduction cartridges share their flash chip command set, so even if yours is not on this list, it may still work fine or even be auto-detected as another one. Support for more cartridges can also be added by creating external config files that include the necessary flash chip commands. -*¹ = Cannot be auto-detected, select cartridge type manually* +*¹ = Cannot always be auto-detected, select cartridge type manually* ### Troubleshooting @@ -269,6 +271,7 @@ The author would like to thank the following very kind people for their help and - 90sFlav (flash chip info) - AcoVanConis (bug reports, flash chip info) +- AdmirtheSableye (bug reports) - AlexiG (GBxCart RW hardware, bug reports, flash chip info) - AndehX (app icon, flash chip info) - antPL (flash chip info) @@ -285,9 +288,11 @@ The author would like to thank the following very kind people for their help and - EmperorOfTigers (bug reports, flash chip info) - endrift (research, mGBA emulator) - eveningmoose (flash chip info) +- FerrantePescara (flash chip info) - frarees (bug reports) - Frost Clock (flash chip info) - Grender (testing) +- HDR (testing) - Herax (flash chip info) - hiks (flash chip info) - howie0210 (flash chip info, bug reports) diff --git a/setup.py b/setup.py index 201df18..9a2c065 100644 --- a/setup.py +++ b/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.8", + version="3.9", 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",