diff --git a/CHANGES.md b/CHANGES.md index 832790f..b189bb7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,4 +1,10 @@ # Release notes +### v3.36 (released 2024-01-15) +- Added support for DIY cart with 28F016S5 *(thanks alexbc2999)* +- Fixed a problem with reading Sachen cartridges *(thanks xukkorz)* +- Updated the Game Boy and Game Boy Advance lookup databases for save types, ROM sizes and checksums +- Minor bug fixes and improvements *(thanks djeddit, AlexiG)* + ### v3.35 (released 2023-11-25) - Added support for DRV with 29LV320DB and ALTERA CPLD *(thanks TheNFCookie)* - Added support for HC007-BGA-V2 with M29W640 *(thanks LucentW)* diff --git a/FlashGBX/FlashGBX_GUI.py b/FlashGBX/FlashGBX_GUI.py index cb82ee3..55bb7fe 100644 --- a/FlashGBX/FlashGBX_GUI.py +++ b/FlashGBX/FlashGBX_GUI.py @@ -558,7 +558,7 @@ class FlashGBX_GUI(QtWidgets.QWidget): print("Error: Failed to check for updates (HTTP status {:d}).".format(ret.status_code)) else: update_check = self.SETTINGS.value("UpdateCheck") - if update_check is None or (time.time() > (Util.VERSION_TIMESTAMP + (2*30*24*60*60))): + if update_check is None or (time.time() > (Util.VERSION_TIMESTAMP + (3*30*24*60*60))): QtWidgets.QMessageBox.information(self, "{:s} {:s}".format(APPNAME, VERSION), "Welcome to {:s} {:s} by Lesserkuma!

".format(APPNAME, VERSION) + "The version update check has been disabled in the config menu and this version is now older than {:d} days. Please regularily check the FlashGBX GitHub page for the latest release notes and updates.".format(int((time.time() - Util.VERSION_TIMESTAMP)/60/60/24)), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok) def DisconnectDevice(self): @@ -1613,7 +1613,7 @@ class FlashGBX_GUI(QtWidgets.QWidget): if "ereader_calibration" in self.CONN.INFO: if erase: buffer = bytearray([0xFF] * 0x20000) - msg_text = "This {:s} cartridge currently has calibration data in place. It is strongly recommended to keep the existing calibration data.\n\nErase everything but the calibration data? Or erase everything?".format(cart_name) + msg_text = "This {:s} cartridge currently has calibration data in place. It is strongly recommended to keep the existing calibration data.\n\nHow do you want to proceed?".format(cart_name) button_overwrite = msgbox.addButton(" &Erase everything ", QtWidgets.QMessageBox.ActionRole) erase = False # Don’t just erase everything else: @@ -2916,27 +2916,35 @@ class FlashGBX_GUI(QtWidgets.QWidget): self.setAcceptDrops(True) self.show() - # Taskbar Progress on Windows only - try: - from PySide2.QtWinExtras import QWinTaskbarButton, QtWin - myappid = 'lesserkuma.flashgbx' - QtWin.setCurrentProcessExplicitAppUserModelID(myappid) - taskbar_button = QWinTaskbarButton() - self.TBPROG = taskbar_button.progress() - self.TBPROG.setRange(0, 100) - taskbar_button.setWindow(self.windowHandle()) - self.TBPROG.setVisible(False) - except ImportError: - pass - - if callable(getattr(qt_app, "exec", None)): - qt_app.exec() # PySide6 - else: - qt_app.exec_() # PySide2 + if callable(getattr(qt_app, "exec", None)): # PySide6 + qt_app.exec() + # Taskbar Progress on Windows only + try: + from PySide6.QtWin import QtWinTaskbarButton, QtWin + myappid = 'lesserkuma.flashgbx' + QtWin.setAppUserModelId(myappid) + taskbar_button = QtWinTaskbarButton() + self.TBPROG = taskbar_button.progress() + self.TBPROG.setRange(0, 100) + taskbar_button.setWindow(self.windowHandle()) + self.TBPROG.setVisible(False) + except ImportError: + pass + + else: # PySide2 + qt_app.exec_() + # Taskbar Progress on Windows only + try: + from PySide2.QtWinExtras import QWinTaskbarButton, QtWin + myappid = 'lesserkuma.flashgbx' + QtWin.setCurrentProcessExplicitAppUserModelID(myappid) + taskbar_button = QWinTaskbarButton() + self.TBPROG = taskbar_button.progress() + self.TBPROG.setRange(0, 100) + taskbar_button.setWindow(self.windowHandle()) + self.TBPROG.setVisible(False) + except ImportError: + pass -os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1" -os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "1" -QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) -QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) qt_app = QApplication(sys.argv) qt_app.setApplicationName(APPNAME) diff --git a/FlashGBX/Util.py b/FlashGBX/Util.py index 1f1bf42..1242926 100644 --- a/FlashGBX/Util.py +++ b/FlashGBX/Util.py @@ -7,9 +7,9 @@ from enum import Enum # Common constants APPNAME = "FlashGBX" -VERSION_PEP440 = "3.35" +VERSION_PEP440 = "3.36" VERSION = "v{:s}".format(VERSION_PEP440) -VERSION_TIMESTAMP = 1700872410 +VERSION_TIMESTAMP = 1705328830 DEBUG = False DEBUG_LOG = [] APP_PATH = "" @@ -870,7 +870,7 @@ def dprint(*args, **kwargs): global DEBUG_LOG stack = traceback.extract_stack() stack = stack[len(stack)-2] - msg = "[{:s}] [{:s}:{:d}] {:s}(): {:s}".format(datetime.datetime.now().astimezone().replace(microsecond=0).isoformat(), stack.filename[stack.filename.replace("\\", "/").rindex("/")+1:], stack.lineno, stack.name, " ".join(map(str, args)), **kwargs) + msg = "[{:s}] [{:s}:{:d}] {:s}(): {:s}".format(datetime.datetime.now().astimezone().replace(microsecond=0).isoformat(), os.path.split(stack.filename)[1], stack.lineno, stack.name, " ".join(map(str, args)), **kwargs) DEBUG_LOG.append(msg) DEBUG_LOG = DEBUG_LOG[-32768:] if DEBUG: diff --git a/FlashGBX/config/db_AGB.json b/FlashGBX/config/db_AGB.json index e042ec7..9778580 100644 --- a/FlashGBX/config/db_AGB.json +++ b/FlashGBX/config/db_AGB.json @@ -5837,6 +5837,18 @@ "lg": "En", "rg": "USA" }, + "47069d46abb14aab342e394d1688d39960ad4c86": { + "gn": "Final Fire Pro Wrestling - Yume no Dantai Unei!", + "ne": "(Japan) (Rev 1)", + "gc": "AFWJ", + "rc": 1066950667, + "rs": 16777216, + "st": 4, + "ss": 65536, + "rv": "Rev 1", + "lg": "Ja", + "rg": "Japan" + }, "ef2b4a1de1f16a46e967650da4bbaf673283572c": { "gn": "Final Fire Pro Wrestling - Yume no Dantai Unei!", "ne": "(Japan)", diff --git a/FlashGBX/config/db_DMG.json b/FlashGBX/config/db_DMG.json index 434f829..c25fa57 100644 --- a/FlashGBX/config/db_DMG.json +++ b/FlashGBX/config/db_DMG.json @@ -109,7 +109,7 @@ }, "296c39c40bdc6061bff718a468b79e7e5f46553e": { "gn": "Pocket Camera - Debug Game Tester - Second Impact", - "ne": "(Japan) (v10.24) (SGB Enhanced) (Test Program)", + "ne": "(Japan) (Test Program) (v10.24) (SGB Enhanced)", "gc": "", "rc": 359820684, "rs": 1048576, @@ -2010,11 +2010,11 @@ }, "114138976f5eba947748ab1c858b14ad93c0c505": { "gn": "Brain Drain", - "ne": "(Japan) (SGB Enhanced)", + "ne": "(Japan) (En) (SGB Enhanced)", "gc": "DMG-ABRJ", "rc": 3847793357, "rs": 131072, - "lg": "Ja", + "lg": "En", "rg": "Japan" }, "525290fa07ff8f3656071a663e4164438191ed15": { @@ -10366,11 +10366,11 @@ }, "5e90d5552a6998dc15dd78fb96a462a7c80548c7": { "gn": "Zoop", - "ne": "(Japan)", + "ne": "(Japan) (En)", "gc": "DMG-AZPJ", "rc": 283222284, "rs": 65536, - "lg": "Ja", + "lg": "En", "rg": "Japan" }, "604c8be3949ba822f41fa3ca9ec46cd2ba6ae4a1": { @@ -21668,7 +21668,7 @@ "rg": "Japan" }, "dd9575d82c7233bc98713ff5020629578eb78373": { - "gn": "Lock n' Chase ~ Lock 'n' Chase", + "gn": "Lock n' Chase", "ne": "(World)", "gc": "DMG-LCA", "rc": 3669564538, diff --git a/FlashGBX/config/fc_DMG_AM29F032_AUDIO.txt b/FlashGBX/config/fc_DMG_AM29F032_AUDIO.txt index fcca528..236c201 100644 --- a/FlashGBX/config/fc_DMG_AM29F032_AUDIO.txt +++ b/FlashGBX/config/fc_DMG_AM29F032_AUDIO.txt @@ -10,7 +10,9 @@ [ 0x04, 0xD4 ], [ 0x04, 0xD4 ], [ 0x20, 0xAC ], - [ 0x04, 0xD4 ] + [ 0x04, 0xD4 ], + [ 0x01, 0x41 ], + [ 0x01, 0xD4 ] ], "voltage":5, "flash_size":0x400000, diff --git a/FlashGBX/config/fc_DMG_iG_8MB.txt b/FlashGBX/config/fc_DMG_iG_8MB.txt index f805498..1f53f00 100644 --- a/FlashGBX/config/fc_DMG_iG_8MB.txt +++ b/FlashGBX/config/fc_DMG_iG_8MB.txt @@ -16,6 +16,7 @@ "write_pin":"WR", "sector_size_from_cfi":true, "chip_erase_timeout":60, + "mbc":"manual", "command_set":"AMD", "commands":{ "reset":[ diff --git a/FlashGBX/fw_GBxCartRW_v1_4.py b/FlashGBX/fw_GBxCartRW_v1_4.py index 4d2b32f..0f0f159 100644 --- a/FlashGBX/fw_GBxCartRW_v1_4.py +++ b/FlashGBX/fw_GBxCartRW_v1_4.py @@ -148,7 +148,7 @@ try: self.lblDevicePCBVer.setMinimumWidth(120) self.optDevicePCBVer14 = QtWidgets.QRadioButton("v1.4") self.connect(self.optDevicePCBVer14, QtCore.SIGNAL("clicked()"), self.SetPCBVersion) - self.optDevicePCBVer14a = QtWidgets.QRadioButton("v1.4a/b") + self.optDevicePCBVer14a = QtWidgets.QRadioButton("v1.4a/b/c") self.connect(self.optDevicePCBVer14a, QtCore.SIGNAL("clicked()"), self.SetPCBVersion) rowDeviceInfo2.addWidget(self.lblDevicePCBVer) rowDeviceInfo2.addWidget(self.optDevicePCBVer14) @@ -217,7 +217,7 @@ try: self.lblDeviceFWVerResult.setText(self.FW_VER) if self.PCB_VER == "v1.4": self.optDevicePCBVer14.setChecked(True) - elif self.PCB_VER == "v1.4a/b": + elif self.PCB_VER == "v1.4a/b/c": self.optDevicePCBVer14a.setChecked(True) self.SetPCBVersion() @@ -275,7 +275,7 @@ try: file_name = self.FWUPD.APP_PATH + "/res/fw_GBxCart_RW_v1_4.zip" led = "Done" elif self.optDevicePCBVer14a.isChecked(): - device_name = "v1.4a/b" + device_name = "v1.4a/b/c" file_name = self.FWUPD.APP_PATH + "/res/fw_GBxCart_RW_v1_4a.zip" led = "Status" else: diff --git a/FlashGBX/hw_GBxCartRW.py b/FlashGBX/hw_GBxCartRW.py index 942d9c3..e1e22d8 100644 --- a/FlashGBX/hw_GBxCartRW.py +++ b/FlashGBX/hw_GBxCartRW.py @@ -92,7 +92,7 @@ class GbxDevice: "AGB_READ_METHOD":[8, 0x0C], } - PCB_VERSIONS = {4:'v1.3', 5:'v1.4', 6:'v1.4a/b', 101:'Mini v1.0d'} + PCB_VERSIONS = {4:'v1.3', 5:'v1.4', 6:'v1.4a/b/c', 101:'Mini v1.0d'} ACTIONS = {"ROM_READ":1, "SAVE_READ":2, "SAVE_WRITE":3, "ROM_WRITE":4, "ROM_WRITE_VERIFY":4, "SAVE_WRITE_VERIFY":3} SUPPORTED_CARTS = {} @@ -174,7 +174,7 @@ class GbxDevice: elif self.FW["fw_ts"] > self.DEVICE_LATEST_FW_TS[self.FW["pcb_ver"]]: conn_msg.append([0, "Note: The GBxCart RW device on port " + ports[i] + " is running a firmware version that is newer than what this version of FlashGBX was developed to work with, so errors may occur."]) - if self.FW["pcb_ver"] not in (4, 5, 6, 101): # only the v1.3, v1.4, v1.4a/b, Mini v1.1 PCB revisions are supported + if self.FW["pcb_ver"] not in (4, 5, 6, 101): # only the v1.3, v1.4, v1.4a/b/c, Mini v1.1 PCB revisions are supported dev.close() self.DEVICE = None continue @@ -385,7 +385,7 @@ class GbxDevice: return (None, fw_GBxCartRW_v1_3.FirmwareUpdaterWindow) except: return False - elif self.FW["pcb_ver"] in (5, 6): # v1.4 / v1.4a/b + elif self.FW["pcb_ver"] in (5, 6): # v1.4 / v1.4a/b/c try: from . import fw_GBxCartRW_v1_4 return (fw_GBxCartRW_v1_4.FirmwareUpdater, fw_GBxCartRW_v1_4.FirmwareUpdaterWindow) @@ -420,6 +420,7 @@ class GbxDevice: if "from_user" in self.CANCEL_ARGS and self.CANCEL_ARGS["from_user"]: return False elif buffer is False: + print("{:s}Error: The USB connection timed out.{:s}".format(ANSI.RED, ANSI.RESET)) dprint("Timeout error ({:s}(), line {:d})".format(stack.name, stack.lineno)) 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: @@ -1415,7 +1416,7 @@ class GbxDevice: return False pos += len(data) - if rumble_stop and pos % flash_buffer_size == 0: + if rumble_stop and flash_buffer_size > 0 and pos % flash_buffer_size == 0: dprint("Sending rumble stop command") self._cart_write(address=0xC6, value=0x00, flashcart=True) rumble_stop = False @@ -2128,6 +2129,9 @@ class GbxDevice: self._set_fw_variable("DMG_READ_CS_PULSE", 1) _mbc.EnableMapper() self._set_fw_variable("DMG_READ_CS_PULSE", 0) + elif _mbc.GetName() == "Sachen": + start_bank = int(args["rom_size"] / 0x4000) + _mbc.SetStartBank(start_bank) else: _mbc.EnableMapper() diff --git a/FlashGBX/pyside.py b/FlashGBX/pyside.py index cf2b722..4138cd3 100644 --- a/FlashGBX/pyside.py +++ b/FlashGBX/pyside.py @@ -5,47 +5,47 @@ # PySide abstraction layer contributed by J-Fox # +import os from .Util import dprint try: - import PySide2, PIL - # PySide2>=5.14 is required - major, minor, *_ = PySide2.__version_info__ - if (major, minor) < (5, 14): - raise ImportError('Requires PySide2>=5.14', name=PySide2.__package__, path=PySide2.__path__) - psversion = 2 - -except ImportError as err: - try: - import PySide6 - except ImportError: - raise err - + import PySide6 dprint('Using PySide6 code path.') psversion = 6 from PySide6 import QtCore from PySide6 import QtWidgets from PySide6 import QtGui from PySide6.QtWidgets import QApplication -else: - dprint('Using PySide2 code path.') - from PySide2 import QtCore - from PySide2 import QtWidgets - from PySide2 import QtGui - from PySide2.QtWidgets import QApplication +except ImportError as err: try: + import PySide2, PIL + # PySide2>=5.14 is required + major, minor, *_ = PySide2.__version_info__ + if (major, minor) < (5, 14): + raise ImportError('Requires PySide2>=5.14', name=PySide2.__package__, path=PySide2.__path__) # Pillow<10.0.0 is required major, minor = map(int, PIL.__version__.split('.')[:2]) if (major, minor) >= (10, 0): - raise ImportError('Requires Pillow<10.0.0', name=PIL.__package__, path=PIL.__path__) + raise ImportError('Requires Pillow<10.0.0 if using PySide2', name=PIL.__package__, path=PIL.__path__) + + dprint('Using PySide2 code path.') + psversion = 2 + from PySide2 import QtCore + from PySide2 import QtWidgets + from PySide2 import QtGui + from PySide2.QtWidgets import QApplication + + os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1" + os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "1" + QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True) + QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True) + except ImportError as err2: raise err2 - __all__ = ['QtCore', 'QtWidgets', 'QtGui', 'QApplication', 'QDesktopWidget'] - class QDesktopWidget(object): def screenGeometry(self, widget): if psversion == 2: diff --git a/FlashGBX/res/config.zip b/FlashGBX/res/config.zip index 15c7402..ca46f93 100644 Binary files a/FlashGBX/res/config.zip and b/FlashGBX/res/config.zip differ diff --git a/README.md b/README.md index 0d739fc..978f9d1 100644 --- a/README.md +++ b/README.md @@ -40,7 +40,7 @@ These work for installing fresh and upgrading from an older version. 1. Download and install [Python](https://www.python.org/downloads/) (version 3.7 or newer) 2. Open a Terminal or Command Prompt window 3. Install FlashGBX with this command:
`pip3 install "FlashGBX[qt6]"` -* If installation fails, use this command instead:
`pip3 install "FlashGBX[qt5]"` +* If installation fails, try this command instead:
`pip3 install "FlashGBX[qt5]"` * If installation still fails, you can install the minimal version (command line interface) with this command:
`pip3 install FlashGBX` * Pre-made Linux packages and instructions for select distributions are available [here](https://github.com/JJ-Fox/FlashGBX-Linux-builds/releases/latest). @@ -100,6 +100,7 @@ Use this command in a Terminal or Command Prompt window to launch the installed - BLAZE Xploder GB - BUNG Doctor GB Card 64M - Catskull 32k Gameboy Flash Cart + - DIY cart with 28F016S5 - DIY cart with AM29F010 - DIY cart with AM29F016/29F016 - DIY cart with AM29F032 @@ -322,7 +323,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, 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, TheNFCookie, 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, TheNFCookie, Timville, twitnic, velipso, Veund, voltagex, Voultar, wickawack, Wkr, x7l7j8cc, xactoes, xukkorz, yosoo, Zeii, Zelante, zipplet, Zoo, zvxr ## DISCLAIMER diff --git a/setup.py b/setup.py index 04cd279..b7fdf75 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.35", + version="3.36", 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",