Skip to content

Commit 83c4b66

Browse files
committed
3.36
1 parent 7c09455 commit 83c4b66

13 files changed

Lines changed: 99 additions & 65 deletions

CHANGES.md

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,10 @@
11
# Release notes
2+
### v3.36 (released 2024-01-15)
3+
- Added support for DIY cart with 28F016S5 *(thanks alexbc2999)*
4+
- Fixed a problem with reading Sachen cartridges *(thanks xukkorz)*
5+
- Updated the Game Boy and Game Boy Advance lookup databases for save types, ROM sizes and checksums
6+
- Minor bug fixes and improvements *(thanks djeddit, AlexiG)*
7+
28
### v3.35 (released 2023-11-25)
39
- Added support for DRV with 29LV320DB and ALTERA CPLD *(thanks TheNFCookie)*
410
- Added support for HC007-BGA-V2 with M29W640 *(thanks LucentW)*

FlashGBX/FlashGBX_GUI.py

Lines changed: 31 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -558,7 +558,7 @@ def UpdateCheck(self):
558558
print("Error: Failed to check for updates (HTTP status {:d}).".format(ret.status_code))
559559
else:
560560
update_check = self.SETTINGS.value("UpdateCheck")
561-
if update_check is None or (time.time() > (Util.VERSION_TIMESTAMP + (2*30*24*60*60))):
561+
if update_check is None or (time.time() > (Util.VERSION_TIMESTAMP + (3*30*24*60*60))):
562562
QtWidgets.QMessageBox.information(self, "{:s} {:s}".format(APPNAME, VERSION), "Welcome to {:s} {:s} by Lesserkuma!<br><br>".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 <a href=\"https://github.com/lesserkuma/FlashGBX/releases/latest\">FlashGBX GitHub page</a> for the latest release notes and updates.".format(int((time.time() - Util.VERSION_TIMESTAMP)/60/60/24)), QtWidgets.QMessageBox.Ok, QtWidgets.QMessageBox.Ok)
563563

564564
def DisconnectDevice(self):
@@ -1613,7 +1613,7 @@ def WriteRAM(self, dpath="", erase=False, test=False):
16131613
if "ereader_calibration" in self.CONN.INFO:
16141614
if erase:
16151615
buffer = bytearray([0xFF] * 0x20000)
1616-
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)
1616+
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)
16171617
button_overwrite = msgbox.addButton(" &Erase everything ", QtWidgets.QMessageBox.ActionRole)
16181618
erase = False # Don’t just erase everything
16191619
else:
@@ -2916,27 +2916,35 @@ def run(self):
29162916
self.setAcceptDrops(True)
29172917
self.show()
29182918

2919-
# Taskbar Progress on Windows only
2920-
try:
2921-
from PySide2.QtWinExtras import QWinTaskbarButton, QtWin
2922-
myappid = 'lesserkuma.flashgbx'
2923-
QtWin.setCurrentProcessExplicitAppUserModelID(myappid)
2924-
taskbar_button = QWinTaskbarButton()
2925-
self.TBPROG = taskbar_button.progress()
2926-
self.TBPROG.setRange(0, 100)
2927-
taskbar_button.setWindow(self.windowHandle())
2928-
self.TBPROG.setVisible(False)
2929-
except ImportError:
2930-
pass
2931-
2932-
if callable(getattr(qt_app, "exec", None)):
2933-
qt_app.exec() # PySide6
2934-
else:
2935-
qt_app.exec_() # PySide2
2919+
if callable(getattr(qt_app, "exec", None)): # PySide6
2920+
qt_app.exec()
2921+
# Taskbar Progress on Windows only
2922+
try:
2923+
from PySide6.QtWin import QtWinTaskbarButton, QtWin
2924+
myappid = 'lesserkuma.flashgbx'
2925+
QtWin.setAppUserModelId(myappid)
2926+
taskbar_button = QtWinTaskbarButton()
2927+
self.TBPROG = taskbar_button.progress()
2928+
self.TBPROG.setRange(0, 100)
2929+
taskbar_button.setWindow(self.windowHandle())
2930+
self.TBPROG.setVisible(False)
2931+
except ImportError:
2932+
pass
2933+
2934+
else: # PySide2
2935+
qt_app.exec_()
2936+
# Taskbar Progress on Windows only
2937+
try:
2938+
from PySide2.QtWinExtras import QWinTaskbarButton, QtWin
2939+
myappid = 'lesserkuma.flashgbx'
2940+
QtWin.setCurrentProcessExplicitAppUserModelID(myappid)
2941+
taskbar_button = QWinTaskbarButton()
2942+
self.TBPROG = taskbar_button.progress()
2943+
self.TBPROG.setRange(0, 100)
2944+
taskbar_button.setWindow(self.windowHandle())
2945+
self.TBPROG.setVisible(False)
2946+
except ImportError:
2947+
pass
29362948

2937-
os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1"
2938-
os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "1"
2939-
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)
2940-
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
29412949
qt_app = QApplication(sys.argv)
29422950
qt_app.setApplicationName(APPNAME)

FlashGBX/Util.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,9 +7,9 @@
77

88
# Common constants
99
APPNAME = "FlashGBX"
10-
VERSION_PEP440 = "3.35"
10+
VERSION_PEP440 = "3.36"
1111
VERSION = "v{:s}".format(VERSION_PEP440)
12-
VERSION_TIMESTAMP = 1700872410
12+
VERSION_TIMESTAMP = 1705328830
1313
DEBUG = False
1414
DEBUG_LOG = []
1515
APP_PATH = ""
@@ -870,7 +870,7 @@ def dprint(*args, **kwargs):
870870
global DEBUG_LOG
871871
stack = traceback.extract_stack()
872872
stack = stack[len(stack)-2]
873-
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)
873+
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)
874874
DEBUG_LOG.append(msg)
875875
DEBUG_LOG = DEBUG_LOG[-32768:]
876876
if DEBUG:

FlashGBX/config/db_AGB.json

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5837,6 +5837,18 @@
58375837
"lg": "En",
58385838
"rg": "USA"
58395839
},
5840+
"47069d46abb14aab342e394d1688d39960ad4c86": {
5841+
"gn": "Final Fire Pro Wrestling - Yume no Dantai Unei!",
5842+
"ne": "(Japan) (Rev 1)",
5843+
"gc": "AFWJ",
5844+
"rc": 1066950667,
5845+
"rs": 16777216,
5846+
"st": 4,
5847+
"ss": 65536,
5848+
"rv": "Rev 1",
5849+
"lg": "Ja",
5850+
"rg": "Japan"
5851+
},
58405852
"ef2b4a1de1f16a46e967650da4bbaf673283572c": {
58415853
"gn": "Final Fire Pro Wrestling - Yume no Dantai Unei!",
58425854
"ne": "(Japan)",

FlashGBX/config/db_DMG.json

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,7 @@
109109
},
110110
"296c39c40bdc6061bff718a468b79e7e5f46553e": {
111111
"gn": "Pocket Camera - Debug Game Tester - Second Impact",
112-
"ne": "(Japan) (v10.24) (SGB Enhanced) (Test Program)",
112+
"ne": "(Japan) (Test Program) (v10.24) (SGB Enhanced)",
113113
"gc": "",
114114
"rc": 359820684,
115115
"rs": 1048576,
@@ -2010,11 +2010,11 @@
20102010
},
20112011
"114138976f5eba947748ab1c858b14ad93c0c505": {
20122012
"gn": "Brain Drain",
2013-
"ne": "(Japan) (SGB Enhanced)",
2013+
"ne": "(Japan) (En) (SGB Enhanced)",
20142014
"gc": "DMG-ABRJ",
20152015
"rc": 3847793357,
20162016
"rs": 131072,
2017-
"lg": "Ja",
2017+
"lg": "En",
20182018
"rg": "Japan"
20192019
},
20202020
"525290fa07ff8f3656071a663e4164438191ed15": {
@@ -10366,11 +10366,11 @@
1036610366
},
1036710367
"5e90d5552a6998dc15dd78fb96a462a7c80548c7": {
1036810368
"gn": "Zoop",
10369-
"ne": "(Japan)",
10369+
"ne": "(Japan) (En)",
1037010370
"gc": "DMG-AZPJ",
1037110371
"rc": 283222284,
1037210372
"rs": 65536,
10373-
"lg": "Ja",
10373+
"lg": "En",
1037410374
"rg": "Japan"
1037510375
},
1037610376
"604c8be3949ba822f41fa3ca9ec46cd2ba6ae4a1": {
@@ -21668,7 +21668,7 @@
2166821668
"rg": "Japan"
2166921669
},
2167021670
"dd9575d82c7233bc98713ff5020629578eb78373": {
21671-
"gn": "Lock n' Chase ~ Lock 'n' Chase",
21671+
"gn": "Lock n' Chase",
2167221672
"ne": "(World)",
2167321673
"gc": "DMG-LCA",
2167421674
"rc": 3669564538,

FlashGBX/config/fc_DMG_AM29F032_AUDIO.txt

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,9 @@
1010
[ 0x04, 0xD4 ],
1111
[ 0x04, 0xD4 ],
1212
[ 0x20, 0xAC ],
13-
[ 0x04, 0xD4 ]
13+
[ 0x04, 0xD4 ],
14+
[ 0x01, 0x41 ],
15+
[ 0x01, 0xD4 ]
1416
],
1517
"voltage":5,
1618
"flash_size":0x400000,

FlashGBX/config/fc_DMG_iG_8MB.txt

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
"write_pin":"WR",
1717
"sector_size_from_cfi":true,
1818
"chip_erase_timeout":60,
19+
"mbc":"manual",
1920
"command_set":"AMD",
2021
"commands":{
2122
"reset":[

FlashGBX/fw_GBxCartRW_v1_4.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -148,7 +148,7 @@ def __init__(self, app, app_path, file=None, icon=None, device=None):
148148
self.lblDevicePCBVer.setMinimumWidth(120)
149149
self.optDevicePCBVer14 = QtWidgets.QRadioButton("v1.4")
150150
self.connect(self.optDevicePCBVer14, QtCore.SIGNAL("clicked()"), self.SetPCBVersion)
151-
self.optDevicePCBVer14a = QtWidgets.QRadioButton("v1.4a/b")
151+
self.optDevicePCBVer14a = QtWidgets.QRadioButton("v1.4a/b/c")
152152
self.connect(self.optDevicePCBVer14a, QtCore.SIGNAL("clicked()"), self.SetPCBVersion)
153153
rowDeviceInfo2.addWidget(self.lblDevicePCBVer)
154154
rowDeviceInfo2.addWidget(self.optDevicePCBVer14)
@@ -217,7 +217,7 @@ def __init__(self, app, app_path, file=None, icon=None, device=None):
217217
self.lblDeviceFWVerResult.setText(self.FW_VER)
218218
if self.PCB_VER == "v1.4":
219219
self.optDevicePCBVer14.setChecked(True)
220-
elif self.PCB_VER == "v1.4a/b":
220+
elif self.PCB_VER == "v1.4a/b/c":
221221
self.optDevicePCBVer14a.setChecked(True)
222222
self.SetPCBVersion()
223223

@@ -275,7 +275,7 @@ def UpdateFirmware(self):
275275
file_name = self.FWUPD.APP_PATH + "/res/fw_GBxCart_RW_v1_4.zip"
276276
led = "Done"
277277
elif self.optDevicePCBVer14a.isChecked():
278-
device_name = "v1.4a/b"
278+
device_name = "v1.4a/b/c"
279279
file_name = self.FWUPD.APP_PATH + "/res/fw_GBxCart_RW_v1_4a.zip"
280280
led = "Status"
281281
else:

FlashGBX/hw_GBxCartRW.py

Lines changed: 8 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -92,7 +92,7 @@ class GbxDevice:
9292
"AGB_READ_METHOD":[8, 0x0C],
9393
}
9494

95-
PCB_VERSIONS = {4:'v1.3', 5:'v1.4', 6:'v1.4a/b', 101:'Mini v1.0d'}
95+
PCB_VERSIONS = {4:'v1.3', 5:'v1.4', 6:'v1.4a/b/c', 101:'Mini v1.0d'}
9696
ACTIONS = {"ROM_READ":1, "SAVE_READ":2, "SAVE_WRITE":3, "ROM_WRITE":4, "ROM_WRITE_VERIFY":4, "SAVE_WRITE_VERIFY":3}
9797
SUPPORTED_CARTS = {}
9898

@@ -174,7 +174,7 @@ def Initialize(self, flashcarts, port=None, max_baud=1700000):
174174
elif self.FW["fw_ts"] > self.DEVICE_LATEST_FW_TS[self.FW["pcb_ver"]]:
175175
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."])
176176

177-
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
177+
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
178178
dev.close()
179179
self.DEVICE = None
180180
continue
@@ -385,7 +385,7 @@ def GetFirmwareUpdaterClass(self):
385385
return (None, fw_GBxCartRW_v1_3.FirmwareUpdaterWindow)
386386
except:
387387
return False
388-
elif self.FW["pcb_ver"] in (5, 6): # v1.4 / v1.4a/b
388+
elif self.FW["pcb_ver"] in (5, 6): # v1.4 / v1.4a/b/c
389389
try:
390390
from . import fw_GBxCartRW_v1_4
391391
return (fw_GBxCartRW_v1_4.FirmwareUpdater, fw_GBxCartRW_v1_4.FirmwareUpdaterWindow)
@@ -420,6 +420,7 @@ def wait_for_ack(self, values=None):
420420
if "from_user" in self.CANCEL_ARGS and self.CANCEL_ARGS["from_user"]:
421421
return False
422422
elif buffer is False:
423+
print("{:s}Error: The USB connection timed out.{:s}".format(ANSI.RED, ANSI.RESET))
423424
dprint("Timeout error ({:s}(), line {:d})".format(stack.name, stack.lineno))
424425
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)})
425426
else:
@@ -1415,7 +1416,7 @@ def WriteROM(self, address, buffer, flash_buffer_size=False, skip_init=False, ru
14151416
return False
14161417
pos += len(data)
14171418

1418-
if rumble_stop and pos % flash_buffer_size == 0:
1419+
if rumble_stop and flash_buffer_size > 0 and pos % flash_buffer_size == 0:
14191420
dprint("Sending rumble stop command")
14201421
self._cart_write(address=0xC6, value=0x00, flashcart=True)
14211422
rumble_stop = False
@@ -2128,6 +2129,9 @@ def _BackupROM(self, args):
21282129
self._set_fw_variable("DMG_READ_CS_PULSE", 1)
21292130
_mbc.EnableMapper()
21302131
self._set_fw_variable("DMG_READ_CS_PULSE", 0)
2132+
elif _mbc.GetName() == "Sachen":
2133+
start_bank = int(args["rom_size"] / 0x4000)
2134+
_mbc.SetStartBank(start_bank)
21312135
else:
21322136
_mbc.EnableMapper()
21332137

FlashGBX/pyside.py

Lines changed: 22 additions & 22 deletions
Original file line numberDiff line numberDiff line change
@@ -5,47 +5,47 @@
55
# PySide abstraction layer contributed by J-Fox
66
#
77

8+
import os
89
from .Util import dprint
910

1011
try:
11-
import PySide2, PIL
12-
# PySide2>=5.14 is required
13-
major, minor, *_ = PySide2.__version_info__
14-
if (major, minor) < (5, 14):
15-
raise ImportError('Requires PySide2>=5.14', name=PySide2.__package__, path=PySide2.__path__)
16-
psversion = 2
17-
18-
except ImportError as err:
19-
try:
20-
import PySide6
21-
except ImportError:
22-
raise err
23-
12+
import PySide6
2413
dprint('Using PySide6 code path.')
2514
psversion = 6
2615
from PySide6 import QtCore
2716
from PySide6 import QtWidgets
2817
from PySide6 import QtGui
2918
from PySide6.QtWidgets import QApplication
30-
else:
31-
dprint('Using PySide2 code path.')
32-
from PySide2 import QtCore
33-
from PySide2 import QtWidgets
34-
from PySide2 import QtGui
35-
from PySide2.QtWidgets import QApplication
3619

20+
except ImportError as err:
3721
try:
22+
import PySide2, PIL
23+
# PySide2>=5.14 is required
24+
major, minor, *_ = PySide2.__version_info__
25+
if (major, minor) < (5, 14):
26+
raise ImportError('Requires PySide2>=5.14', name=PySide2.__package__, path=PySide2.__path__)
3827
# Pillow<10.0.0 is required
3928
major, minor = map(int, PIL.__version__.split('.')[:2])
4029
if (major, minor) >= (10, 0):
41-
raise ImportError('Requires Pillow<10.0.0', name=PIL.__package__, path=PIL.__path__)
30+
raise ImportError('Requires Pillow<10.0.0 if using PySide2', name=PIL.__package__, path=PIL.__path__)
31+
32+
dprint('Using PySide2 code path.')
33+
psversion = 2
34+
from PySide2 import QtCore
35+
from PySide2 import QtWidgets
36+
from PySide2 import QtGui
37+
from PySide2.QtWidgets import QApplication
38+
39+
os.environ["QT_AUTO_SCREEN_SCALE_FACTOR"] = "1"
40+
os.environ["QT_ENABLE_HIGHDPI_SCALING"] = "1"
41+
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_EnableHighDpiScaling, True)
42+
QtCore.QCoreApplication.setAttribute(QtCore.Qt.AA_UseHighDpiPixmaps, True)
43+
4244
except ImportError as err2:
4345
raise err2
4446

45-
4647
__all__ = ['QtCore', 'QtWidgets', 'QtGui', 'QApplication', 'QDesktopWidget']
4748

48-
4949
class QDesktopWidget(object):
5050
def screenGeometry(self, widget):
5151
if psversion == 2:

0 commit comments

Comments
 (0)