This commit is contained in:
Lesserkuma
2023-09-25 12:19:31 +02:00
parent 64c4429f14
commit cff844d67b
9 changed files with 90 additions and 62 deletions

View File

@@ -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

View File

@@ -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

View File

@@ -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":

View File

@@ -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

View File

@@ -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 ] }

View File

@@ -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 its possible not all bytes are transmitted successfully,
# even though were 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

View File

@@ -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

View File

@@ -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

View File

@@ -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",