FlashGBX 3.37__py3-none-any.whl → 4.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- FlashGBX/FlashGBX.py +14 -7
- FlashGBX/FlashGBX_CLI.py +201 -24
- FlashGBX/FlashGBX_GUI.py +636 -204
- FlashGBX/Flashcart.py +184 -83
- FlashGBX/GBMemory.py +4 -5
- FlashGBX/LK_Device.py +4526 -0
- FlashGBX/Mapper.py +534 -356
- FlashGBX/RomFileAGB.py +92 -2
- FlashGBX/RomFileDMG.py +1 -1
- FlashGBX/UserInputDialog.py +20 -0
- FlashGBX/Util.py +95 -47
- FlashGBX/fw_GBFlash.py +426 -0
- FlashGBX/fw_GBxCartRW_v1_3.py +1 -1
- FlashGBX/fw_JoeyJr.py +472 -0
- FlashGBX/hw_GBFlash.py +244 -0
- FlashGBX/hw_GBxCartRW.py +200 -3777
- FlashGBX/hw_JoeyJr.py +309 -0
- FlashGBX/res/Third Party Notices.md +342 -0
- FlashGBX/res/config.zip +0 -0
- FlashGBX/res/fw_GBFlash.zip +0 -0
- FlashGBX/res/fw_GBxCart_RW_v1_3.zip +0 -0
- FlashGBX/res/fw_GBxCart_RW_v1_4.zip +0 -0
- FlashGBX/res/fw_GBxCart_RW_v1_4a.zip +0 -0
- FlashGBX/res/fw_JoeyJr.zip +0 -0
- {FlashGBX-3.37.dist-info → FlashGBX-4.0.dist-info}/METADATA +33 -14
- FlashGBX-4.0.dist-info/RECORD +43 -0
- FlashGBX/hw_GBxCartRW_ofw.py +0 -2599
- FlashGBX-3.37.dist-info/RECORD +0 -36
- {FlashGBX-3.37.dist-info → FlashGBX-4.0.dist-info}/LICENSE +0 -0
- {FlashGBX-3.37.dist-info → FlashGBX-4.0.dist-info}/WHEEL +0 -0
- {FlashGBX-3.37.dist-info → FlashGBX-4.0.dist-info}/entry_points.txt +0 -0
- {FlashGBX-3.37.dist-info → FlashGBX-4.0.dist-info}/top_level.txt +0 -0
FlashGBX/fw_JoeyJr.py
ADDED
|
@@ -0,0 +1,472 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# FlashGBX
|
|
3
|
+
# Author: Lesserkuma (github.com/lesserkuma)
|
|
4
|
+
|
|
5
|
+
import zipfile, time, os, struct, serial, platform
|
|
6
|
+
try:
|
|
7
|
+
from . import Util
|
|
8
|
+
except ImportError:
|
|
9
|
+
import Util
|
|
10
|
+
|
|
11
|
+
class FirmwareUpdater():
|
|
12
|
+
PORT = None
|
|
13
|
+
DEVICE = None
|
|
14
|
+
|
|
15
|
+
def __init__(self, app_path=".", port=None):
|
|
16
|
+
self.APP_PATH = app_path
|
|
17
|
+
self.PORT = port
|
|
18
|
+
|
|
19
|
+
def CalcChecksum(self, buffer):
|
|
20
|
+
checksum = 0
|
|
21
|
+
for value in buffer[:0xFFFC]:
|
|
22
|
+
checksum += value
|
|
23
|
+
return checksum
|
|
24
|
+
|
|
25
|
+
def TryConnect(self, port):
|
|
26
|
+
return True
|
|
27
|
+
|
|
28
|
+
def WriteFirmwareMSC(self, path, buffer, fncSetStatus):
|
|
29
|
+
file = path
|
|
30
|
+
path = os.path.dirname(path) + "/"
|
|
31
|
+
fncSetStatus(text="Connecting... This may take a moment.")
|
|
32
|
+
|
|
33
|
+
with open(file, "rb") as f: temp = f.read().decode("UTF-8", "ignore")
|
|
34
|
+
if not temp.startswith("UPDATE"):
|
|
35
|
+
with open(file, "w", encoding="UTF-8") as f: f.write("UPDATE\r\n")
|
|
36
|
+
hp = 30
|
|
37
|
+
while hp > 0:
|
|
38
|
+
if os.path.exists(path + "FIRMWARE.JR"): break
|
|
39
|
+
time.sleep(1)
|
|
40
|
+
hp -= 1
|
|
41
|
+
if hp == 0:
|
|
42
|
+
fncSetStatus(text="Error: Couldn’t communicate with the Joey Jr device.")
|
|
43
|
+
return 2
|
|
44
|
+
|
|
45
|
+
with open(file, "rb") as f: temp = f.read().decode("UTF-8", "ignore")
|
|
46
|
+
if not temp.startswith("UPDATE"):
|
|
47
|
+
fncSetStatus(text="Error: Couldn’t enter UPDATE mode, please try again.")
|
|
48
|
+
return 2
|
|
49
|
+
|
|
50
|
+
fncSetStatus(text="Updating firmware... Do not unplug the device!", setProgress=0)
|
|
51
|
+
os.unlink(path + "FIRMWARE.JR")
|
|
52
|
+
if os.path.exists(path + "FIRMWARE.JR"):
|
|
53
|
+
fncSetStatus(text="Error: Couldn’t write new firmware, please try again.")
|
|
54
|
+
return 2
|
|
55
|
+
|
|
56
|
+
try:
|
|
57
|
+
f = open(path + "FIRMWARE.JR", "wb")
|
|
58
|
+
except OSError:
|
|
59
|
+
fncSetStatus(text="Error: Couldn’t write new firmware, please try again.")
|
|
60
|
+
return 2
|
|
61
|
+
|
|
62
|
+
for i in range(0, len(buffer), 64):
|
|
63
|
+
f.write(buffer[i:i+64])
|
|
64
|
+
percent = float(i + 64) / len(buffer) * 100
|
|
65
|
+
fncSetStatus(text="Updating firmware... Do not unplug the device!", setProgress=percent)
|
|
66
|
+
|
|
67
|
+
try:
|
|
68
|
+
f.close()
|
|
69
|
+
except OSError:
|
|
70
|
+
pass
|
|
71
|
+
|
|
72
|
+
time.sleep(3)
|
|
73
|
+
fncSetStatus("Done.")
|
|
74
|
+
time.sleep(1)
|
|
75
|
+
|
|
76
|
+
return True
|
|
77
|
+
|
|
78
|
+
def WriteFirmware(self, buffer, fncSetStatus):
|
|
79
|
+
if struct.unpack(">I", buffer[0xFFFC:0x10000])[0] != self.CalcChecksum(buffer): return 3
|
|
80
|
+
|
|
81
|
+
# Check for serial mode
|
|
82
|
+
if self.PORT is None:
|
|
83
|
+
ports = []
|
|
84
|
+
comports = serial.tools.list_ports.comports()
|
|
85
|
+
for i in range(0, len(comports)):
|
|
86
|
+
if comports[i].vid == 0x483 and comports[i].pid == 0x5740:
|
|
87
|
+
ports.append(comports[i].device)
|
|
88
|
+
if len(ports) == 0:
|
|
89
|
+
return 4
|
|
90
|
+
port = ports[0]
|
|
91
|
+
else:
|
|
92
|
+
port = self.PORT
|
|
93
|
+
|
|
94
|
+
while True:
|
|
95
|
+
fncSetStatus(text="Connecting...")
|
|
96
|
+
try:
|
|
97
|
+
dev = serial.Serial(port, 2000000, timeout=0.2)
|
|
98
|
+
except:
|
|
99
|
+
fncSetStatus(text="Device not accessible.", enableUI=True)
|
|
100
|
+
return 2
|
|
101
|
+
dev.reset_input_buffer()
|
|
102
|
+
|
|
103
|
+
fncSetStatus("Identifying device...")
|
|
104
|
+
dev.write(b'\x55\xAA')
|
|
105
|
+
time.sleep(0.01)
|
|
106
|
+
device_id = dev.read(dev.in_waiting)
|
|
107
|
+
|
|
108
|
+
if b"Joey" not in device_id:
|
|
109
|
+
# print("Not a Joey Jr")
|
|
110
|
+
fncSetStatus("Joey Jr device not found.")
|
|
111
|
+
return 2
|
|
112
|
+
|
|
113
|
+
if b"FW L" in device_id and device_id[-1] != 0:
|
|
114
|
+
fncSetStatus("Rebooting device...")
|
|
115
|
+
dev.write(b'\xF1')
|
|
116
|
+
dev.read(1)
|
|
117
|
+
dev.write(b'\x01')
|
|
118
|
+
dev.close()
|
|
119
|
+
time.sleep(0.5)
|
|
120
|
+
continue
|
|
121
|
+
break
|
|
122
|
+
|
|
123
|
+
dev.write(b'\xFE\x01')
|
|
124
|
+
time.sleep(0.01)
|
|
125
|
+
dev.read(1)
|
|
126
|
+
# print("")
|
|
127
|
+
|
|
128
|
+
size = len(buffer)
|
|
129
|
+
counter = 0
|
|
130
|
+
while counter < size:
|
|
131
|
+
percent = float(counter)/size*100
|
|
132
|
+
fw_buffer = buffer[counter:counter+64]
|
|
133
|
+
dev.write(fw_buffer)
|
|
134
|
+
time.sleep(0.001)
|
|
135
|
+
try:
|
|
136
|
+
temp = dev.read(dev.in_waiting)
|
|
137
|
+
except:
|
|
138
|
+
temp = False
|
|
139
|
+
if temp is not False:
|
|
140
|
+
# print("Flashing...", hex(i), end="\r")
|
|
141
|
+
pass
|
|
142
|
+
elif counter + 64 < size:
|
|
143
|
+
print("\nBad response at", counter)
|
|
144
|
+
fncSetStatus(text="Error: Bad response at 0x{:X}!".format(counter), setProgress=percent)
|
|
145
|
+
return 2
|
|
146
|
+
|
|
147
|
+
counter += 64
|
|
148
|
+
fncSetStatus(text="Updating firmware... Do not unplug the device!", setProgress=percent)
|
|
149
|
+
|
|
150
|
+
dev.close()
|
|
151
|
+
time.sleep(0.8)
|
|
152
|
+
fncSetStatus("Done.", setProgress=100)
|
|
153
|
+
time.sleep(1)
|
|
154
|
+
return 1
|
|
155
|
+
|
|
156
|
+
try:
|
|
157
|
+
from .pyside import QtCore, QtWidgets, QtGui, QDesktopWidget
|
|
158
|
+
class FirmwareUpdaterWindow(QtWidgets.QDialog):
|
|
159
|
+
APP = None
|
|
160
|
+
DEVICE = None
|
|
161
|
+
FWUPD = None
|
|
162
|
+
DEV_NAME = "Joey Jr"
|
|
163
|
+
FW_VER = ""
|
|
164
|
+
PCB_VER = ""
|
|
165
|
+
|
|
166
|
+
def __init__(self, app, app_path, file=None, icon=None, device=None):
|
|
167
|
+
QtWidgets.QDialog.__init__(self)
|
|
168
|
+
if icon is not None: self.setWindowIcon(QtGui.QIcon(icon))
|
|
169
|
+
self.setStyleSheet("QMessageBox { messagebox-text-interaction-flags: 5; }")
|
|
170
|
+
self.setWindowTitle("FlashGBX – Firmware Updater for Joey Jr")
|
|
171
|
+
self.setWindowFlags((self.windowFlags() | QtCore.Qt.MSWindowsFixedSizeDialogHint) & ~QtCore.Qt.WindowContextHelpButtonHint)
|
|
172
|
+
|
|
173
|
+
self.APP = app
|
|
174
|
+
if device is not None:
|
|
175
|
+
self.FWUPD = FirmwareUpdater(app_path, device.GetPort())
|
|
176
|
+
self.DEV_NAME = device.GetName()
|
|
177
|
+
self.FW_VER = device.GetFirmwareVersion(more=True)
|
|
178
|
+
self.PCB_VER = device.GetPCBVersion()
|
|
179
|
+
self.DEVICE = device
|
|
180
|
+
else:
|
|
181
|
+
self.APP.QT_APP.processEvents()
|
|
182
|
+
self.FWUPD = FirmwareUpdater(app_path, None)
|
|
183
|
+
|
|
184
|
+
self.layout = QtWidgets.QGridLayout()
|
|
185
|
+
self.layout.setContentsMargins(-1, 8, -1, 8)
|
|
186
|
+
self.layout.setSizeConstraint(QtWidgets.QLayout.SetFixedSize)
|
|
187
|
+
self.layout_device = QtWidgets.QVBoxLayout()
|
|
188
|
+
|
|
189
|
+
# ↓↓↓ Current Device Information
|
|
190
|
+
self.grpDeviceInfo = QtWidgets.QGroupBox("Current Firmware")
|
|
191
|
+
self.grpDeviceInfo.setMinimumWidth(420)
|
|
192
|
+
self.grpDeviceInfoLayout = QtWidgets.QVBoxLayout()
|
|
193
|
+
self.grpDeviceInfoLayout.setContentsMargins(-1, 3, -1, -1)
|
|
194
|
+
rowDeviceInfo1 = QtWidgets.QHBoxLayout()
|
|
195
|
+
self.lblDeviceName = QtWidgets.QLabel("Device:")
|
|
196
|
+
self.lblDeviceName.setMinimumWidth(120)
|
|
197
|
+
self.lblDeviceNameResult = QtWidgets.QLabel("Joey Jr")
|
|
198
|
+
rowDeviceInfo1.addWidget(self.lblDeviceName)
|
|
199
|
+
rowDeviceInfo1.addWidget(self.lblDeviceNameResult)
|
|
200
|
+
rowDeviceInfo1.addStretch(1)
|
|
201
|
+
self.grpDeviceInfoLayout.addLayout(rowDeviceInfo1)
|
|
202
|
+
rowDeviceInfo3 = QtWidgets.QHBoxLayout()
|
|
203
|
+
self.lblDeviceFWVer = QtWidgets.QLabel("Firmware version:")
|
|
204
|
+
self.lblDeviceFWVer.setMinimumWidth(120)
|
|
205
|
+
self.lblDeviceFWVerResult = QtWidgets.QLabel("L12")
|
|
206
|
+
rowDeviceInfo3.addWidget(self.lblDeviceFWVer)
|
|
207
|
+
rowDeviceInfo3.addWidget(self.lblDeviceFWVerResult)
|
|
208
|
+
rowDeviceInfo3.addStretch(1)
|
|
209
|
+
self.grpDeviceInfoLayout.addLayout(rowDeviceInfo3)
|
|
210
|
+
self.grpDeviceInfo.setLayout(self.grpDeviceInfoLayout)
|
|
211
|
+
self.layout_device.addWidget(self.grpDeviceInfo)
|
|
212
|
+
# ↑↑↑ Current Device Information
|
|
213
|
+
|
|
214
|
+
# ↓↓↓ Available Firmware Updates
|
|
215
|
+
file_name = self.FWUPD.APP_PATH + "/res/fw_JoeyJr.zip"
|
|
216
|
+
|
|
217
|
+
with zipfile.ZipFile(file_name) as zip:
|
|
218
|
+
with zip.open("fw.ini") as f: ini_file = f.read()
|
|
219
|
+
ini_file = ini_file.decode(encoding="utf-8")
|
|
220
|
+
self.INI = Util.IniSettings(ini=ini_file, main_section="Firmware")
|
|
221
|
+
self.FW_LK_VER = self.INI.GetValue("fw_ver")
|
|
222
|
+
self.FW_LK_BUILDTS = self.INI.GetValue("fw_buildts")
|
|
223
|
+
self.FW_LK_TEXT = self.INI.GetValue("fw_text")
|
|
224
|
+
self.FW_MSC_VER = self.INI.GetValue("fw_msc_ver")
|
|
225
|
+
self.FW_MSC_TEXT = self.INI.GetValue("fw_msc_text")
|
|
226
|
+
self.FW_JOEYGUI_VER = self.INI.GetValue("fw_joeygui_ver")
|
|
227
|
+
self.FW_JOEYGUI_TEXT = self.INI.GetValue("fw_joeygui_text")
|
|
228
|
+
|
|
229
|
+
self.grpAvailableFwUpdates = QtWidgets.QGroupBox("Firmware Update Options")
|
|
230
|
+
self.grpAvailableFwUpdates.setMinimumWidth(400)
|
|
231
|
+
self.grpAvailableFwUpdatesLayout = QtWidgets.QVBoxLayout()
|
|
232
|
+
self.grpAvailableFwUpdatesLayout.setContentsMargins(-1, 3, -1, -1)
|
|
233
|
+
|
|
234
|
+
self.optFW_LK = QtWidgets.QRadioButton("{:s}".format(self.FW_LK_VER))
|
|
235
|
+
self.lblFW_LK_Blerb = QtWidgets.QLabel("{:s}".format(self.FW_LK_TEXT))
|
|
236
|
+
self.lblFW_LK_Blerb.setWordWrap(True)
|
|
237
|
+
self.lblFW_LK_Blerb.mousePressEvent = lambda x: [ self.optFW_LK.setChecked(True) ]
|
|
238
|
+
self.optFW_MSC = QtWidgets.QRadioButton("{:s}".format(self.FW_MSC_VER))
|
|
239
|
+
self.lblFW_MSC_Blerb = QtWidgets.QLabel("{:s}".format(self.FW_MSC_TEXT))
|
|
240
|
+
self.lblFW_MSC_Blerb.setWordWrap(True)
|
|
241
|
+
self.lblFW_MSC_Blerb.mousePressEvent = lambda x: [ self.optFW_MSC.setChecked(True) ]
|
|
242
|
+
self.optFW_JoeyGUI = QtWidgets.QRadioButton("{:s}".format(self.FW_JOEYGUI_VER))
|
|
243
|
+
self.lblFW_JoeyGUI_Blerb = QtWidgets.QLabel("{:s}".format(self.FW_JOEYGUI_TEXT))
|
|
244
|
+
self.lblFW_JoeyGUI_Blerb.setWordWrap(True)
|
|
245
|
+
self.lblFW_JoeyGUI_Blerb.mousePressEvent = lambda x: [ self.optFW_JoeyGUI.setChecked(True) ]
|
|
246
|
+
self.optExternal = QtWidgets.QRadioButton("External FIRMWARE.JR file")
|
|
247
|
+
|
|
248
|
+
self.rowUpdate = QtWidgets.QHBoxLayout()
|
|
249
|
+
self.btnUpdate = QtWidgets.QPushButton("Install Firmware Update")
|
|
250
|
+
self.btnUpdate.setMinimumWidth(200)
|
|
251
|
+
self.btnUpdate.setContentsMargins(20, 20, 20, 20)
|
|
252
|
+
self.connect(self.btnUpdate, QtCore.SIGNAL("clicked()"), lambda: [ self.UpdateFirmware() ])
|
|
253
|
+
self.rowUpdate.addStretch()
|
|
254
|
+
self.rowUpdate.addWidget(self.btnUpdate)
|
|
255
|
+
self.rowUpdate.addStretch()
|
|
256
|
+
|
|
257
|
+
self.rowUpdate2 = QtWidgets.QHBoxLayout()
|
|
258
|
+
self.lblUpdateDisclaimer = QtWidgets.QLabel("Please note that FlashGBX is not officially supported by BennVenn, so please use this firmware updater at your own risk.")
|
|
259
|
+
self.lblUpdateDisclaimer.setWordWrap(True)
|
|
260
|
+
self.lblUpdateDisclaimer.setAlignment(QtGui.Qt.AlignmentFlag.AlignCenter)
|
|
261
|
+
self.rowUpdate2.addWidget(self.lblUpdateDisclaimer)
|
|
262
|
+
|
|
263
|
+
self.grpAvailableFwUpdatesLayout.addWidget(self.optFW_LK)
|
|
264
|
+
self.grpAvailableFwUpdatesLayout.addWidget(self.lblFW_LK_Blerb)
|
|
265
|
+
self.optFW_LK.setChecked(True)
|
|
266
|
+
self.grpAvailableFwUpdatesLayout.addWidget(self.optFW_MSC)
|
|
267
|
+
self.grpAvailableFwUpdatesLayout.addWidget(self.lblFW_MSC_Blerb)
|
|
268
|
+
self.grpAvailableFwUpdatesLayout.addWidget(self.optFW_JoeyGUI)
|
|
269
|
+
self.grpAvailableFwUpdatesLayout.addWidget(self.lblFW_JoeyGUI_Blerb)
|
|
270
|
+
self.grpAvailableFwUpdatesLayout.addWidget(self.optExternal)
|
|
271
|
+
self.grpAvailableFwUpdatesLayout.addSpacing(3)
|
|
272
|
+
self.grpAvailableFwUpdatesLayout.addItem(self.rowUpdate)
|
|
273
|
+
self.grpAvailableFwUpdatesLayout.addItem(self.rowUpdate2)
|
|
274
|
+
self.grpAvailableFwUpdates.setLayout(self.grpAvailableFwUpdatesLayout)
|
|
275
|
+
self.layout_device.addWidget(self.grpAvailableFwUpdates)
|
|
276
|
+
# ↑↑↑ Available Firmware Updates
|
|
277
|
+
|
|
278
|
+
self.grpStatus = QtWidgets.QGroupBox("")
|
|
279
|
+
self.grpStatusLayout = QtWidgets.QGridLayout()
|
|
280
|
+
self.prgStatus = QtWidgets.QProgressBar()
|
|
281
|
+
self.prgStatus.setMinimum(0)
|
|
282
|
+
self.prgStatus.setMaximum(1000)
|
|
283
|
+
self.prgStatus.setValue(0)
|
|
284
|
+
self.lblStatus = QtWidgets.QLabel("Ready.")
|
|
285
|
+
|
|
286
|
+
self.grpStatusLayout.addWidget(self.prgStatus, 1, 0)
|
|
287
|
+
self.grpStatusLayout.addWidget(self.lblStatus, 2, 0)
|
|
288
|
+
|
|
289
|
+
self.grpStatus.setLayout(self.grpStatusLayout)
|
|
290
|
+
self.layout_device.addWidget(self.grpStatus)
|
|
291
|
+
|
|
292
|
+
self.grpFooterLayout = QtWidgets.QHBoxLayout()
|
|
293
|
+
self.btnClose = QtWidgets.QPushButton("&Close")
|
|
294
|
+
self.connect(self.btnClose, QtCore.SIGNAL("clicked()"), lambda: [ self.reject() ])
|
|
295
|
+
self.grpFooterLayout.addStretch()
|
|
296
|
+
self.grpFooterLayout.addWidget(self.btnClose)
|
|
297
|
+
self.layout_device.addItem(self.grpFooterLayout)
|
|
298
|
+
|
|
299
|
+
self.layout.addLayout(self.layout_device, 0, 0)
|
|
300
|
+
self.setLayout(self.layout)
|
|
301
|
+
|
|
302
|
+
self.lblDeviceNameResult.setText(self.DEV_NAME + " " + self.PCB_VER)
|
|
303
|
+
self.lblDeviceFWVerResult.setText(self.FW_VER)
|
|
304
|
+
|
|
305
|
+
if platform.system() == 'Darwin':
|
|
306
|
+
self.optFW_MSC.setVisible(False)
|
|
307
|
+
self.lblFW_MSC_Blerb.setVisible(False)
|
|
308
|
+
|
|
309
|
+
def run(self):
|
|
310
|
+
try:
|
|
311
|
+
self.layout.update()
|
|
312
|
+
self.layout.activate()
|
|
313
|
+
screenGeometry = QDesktopWidget().screenGeometry(self)
|
|
314
|
+
x = (screenGeometry.width() - self.width()) / 2
|
|
315
|
+
y = (screenGeometry.height() - self.height()) / 2
|
|
316
|
+
self.move(x, y)
|
|
317
|
+
self.show()
|
|
318
|
+
except:
|
|
319
|
+
return
|
|
320
|
+
|
|
321
|
+
def hideEvent(self, event):
|
|
322
|
+
if self.DEVICE is None:
|
|
323
|
+
self.APP.ConnectDevice()
|
|
324
|
+
self.APP.activateWindow()
|
|
325
|
+
|
|
326
|
+
def reject(self):
|
|
327
|
+
if self.CloseDialog():
|
|
328
|
+
super().reject()
|
|
329
|
+
|
|
330
|
+
def CloseDialog(self):
|
|
331
|
+
if self.btnClose.isEnabled() is False:
|
|
332
|
+
text = "<b>WARNING:</b> If you close this window while a firmware update is still running, it may leave the device in an unbootable state. You can still recover it by running the Firmware Updater again later.<br><br>Are you sure you want to close this window?"
|
|
333
|
+
msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Warning, windowTitle="FlashGBX", text=text, standardButtons=QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
|
|
334
|
+
msgbox.setDefaultButton(QtWidgets.QMessageBox.No)
|
|
335
|
+
answer = msgbox.exec()
|
|
336
|
+
if answer == QtWidgets.QMessageBox.No: return False
|
|
337
|
+
return True
|
|
338
|
+
|
|
339
|
+
def UpdateFirmware(self):
|
|
340
|
+
with zipfile.ZipFile(self.FWUPD.APP_PATH + "/res/fw_JoeyJr.zip") as archive:
|
|
341
|
+
fw = ""
|
|
342
|
+
path = ""
|
|
343
|
+
verified = False
|
|
344
|
+
if self.optFW_LK.isChecked():
|
|
345
|
+
fw = self.FW_LK_VER
|
|
346
|
+
fn = "FIRMWARE_LK.JR"
|
|
347
|
+
with archive.open(fn) as f: fw_data = bytearray(f.read())
|
|
348
|
+
if (b"Joey Jr" in fw_data and b"FW LK" in fw_data): verified = True
|
|
349
|
+
elif self.optFW_MSC.isChecked():
|
|
350
|
+
fw = self.FW_MSC_VER
|
|
351
|
+
fn = "FIRMWARE_MSC.JR"
|
|
352
|
+
with archive.open(fn) as f: fw_data = bytearray(f.read())
|
|
353
|
+
if (b"Joey Jr. Firmware" in fw_data): verified = True
|
|
354
|
+
elif self.optFW_JoeyGUI.isChecked():
|
|
355
|
+
fw = self.FW_JOEYGUI_VER
|
|
356
|
+
fn = "FIRMWARE_JOEYGUI.JR"
|
|
357
|
+
with archive.open(fn) as f: fw_data = bytearray(f.read())
|
|
358
|
+
if (b"Joey Jr" in fw_data and b"FW GUI" in fw_data): verified = True
|
|
359
|
+
else:
|
|
360
|
+
path = self.APP.SETTINGS.value("LastDirFirmwareUpdate")
|
|
361
|
+
path = QtWidgets.QFileDialog.getOpenFileName(self, "Choose Joey Jr Firmware File", path, "Firmware Update (FIRMWARE.JR)")[0]
|
|
362
|
+
if path == "": return
|
|
363
|
+
if not os.path.basename(path).endswith(".JR"):
|
|
364
|
+
msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Critical, windowTitle="FlashGBX", text="The expected filename for a valid firmware file is <b>FIRMWARE.JR</b>. Please visit <a href=\"https://bennvenn.myshopify.com/products/usb-gb-c-cart-dumper-the-joey-jr\">https://bennvenn.myshopify.com/products/usb-gb-c-cart-dumper-the-joey-jr</a> for the latest official firmware updates.", standardButtons=QtWidgets.QMessageBox.Ok)
|
|
365
|
+
answer = msgbox.exec()
|
|
366
|
+
return
|
|
367
|
+
elif os.path.exists(os.path.dirname(path) + "DEBUG.TXT"):
|
|
368
|
+
msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Critical, windowTitle="FlashGBX", text="The selected file can not be used. Please visit <a href=\"https://bennvenn.myshopify.com/products/usb-gb-c-cart-dumper-the-joey-jr\">https://bennvenn.myshopify.com/products/usb-gb-c-cart-dumper-the-joey-jr</a> for the latest official firmware updates.", standardButtons=QtWidgets.QMessageBox.Ok)
|
|
369
|
+
answer = msgbox.exec()
|
|
370
|
+
return
|
|
371
|
+
self.APP.SETTINGS.setValue("LastDirFirmwareUpdate", os.path.dirname(path))
|
|
372
|
+
fw = path
|
|
373
|
+
fn = None
|
|
374
|
+
try:
|
|
375
|
+
with open(path, "rb") as f: fw_data = bytearray(f.read())
|
|
376
|
+
index_from = fw_data.index(b"Joey Jr")
|
|
377
|
+
index_to = fw_data[index_from:].index(b"\x00")
|
|
378
|
+
fw_string = fw_data[index_from:index_from+index_to].decode("ASCII", "ignore")
|
|
379
|
+
if "Firmware" in fw_string:
|
|
380
|
+
fw += "<br><br><b>Detected firmware string:</b><br>" + fw_string
|
|
381
|
+
if "N64 Firmware" in fw_string: raise ValueError("N64 Firmware found")
|
|
382
|
+
if "Jr4Gen3 Firmware" in fw_string: raise ValueError("Jr4Gen3 Firmware found")
|
|
383
|
+
verified = True
|
|
384
|
+
if len(fw_data) > 0x10000:
|
|
385
|
+
verified = False
|
|
386
|
+
raise ValueError("Firmware file is too large")
|
|
387
|
+
except ValueError as e:
|
|
388
|
+
fw += f"<br><br><b>Warning:</b> The selected firmware file couldn’t be confirmed to be valid automatically ({str(e)}). Please double check that this is a valid firmware file for your Joey Jr. If it is invalid or an update for a different device, it may render your device unusable."
|
|
389
|
+
except:
|
|
390
|
+
verified = False
|
|
391
|
+
|
|
392
|
+
if verified is False:
|
|
393
|
+
text = "The firmware update file is corrupted."
|
|
394
|
+
self.btnUpdate.setEnabled(True)
|
|
395
|
+
self.btnClose.setEnabled(True)
|
|
396
|
+
msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Critical, windowTitle="FlashGBX", text=text, standardButtons=QtWidgets.QMessageBox.Ok)
|
|
397
|
+
answer = msgbox.exec()
|
|
398
|
+
return False
|
|
399
|
+
|
|
400
|
+
text = "The following firmware will now be written to your Joey Jr device:<br>- {:s}".format(fw)
|
|
401
|
+
text += "<br><br>Do you want to continue?"
|
|
402
|
+
msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Question, windowTitle="FlashGBX", text=text, standardButtons=QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
|
|
403
|
+
msgbox.setDefaultButton(QtWidgets.QMessageBox.Yes)
|
|
404
|
+
msgbox.setTextFormat(QtCore.Qt.TextFormat.RichText)
|
|
405
|
+
answer = msgbox.exec()
|
|
406
|
+
if answer == QtWidgets.QMessageBox.No: return
|
|
407
|
+
self.grpAvailableFwUpdates.setEnabled(False)
|
|
408
|
+
self.btnUpdate.setEnabled(False)
|
|
409
|
+
self.btnClose.setEnabled(False)
|
|
410
|
+
|
|
411
|
+
self.APP.DisconnectDevice()
|
|
412
|
+
|
|
413
|
+
ret = 0
|
|
414
|
+
while True:
|
|
415
|
+
if ret == 4:
|
|
416
|
+
ret = self.FWUPD.WriteFirmwareMSC(path, fw_data, self.SetStatus)
|
|
417
|
+
else:
|
|
418
|
+
ret = self.FWUPD.WriteFirmware(fw_data, self.SetStatus)
|
|
419
|
+
|
|
420
|
+
if ret == 1:
|
|
421
|
+
text = "The firmware update is complete!"
|
|
422
|
+
self.grpAvailableFwUpdates.setEnabled(True)
|
|
423
|
+
self.btnUpdate.setEnabled(True)
|
|
424
|
+
self.btnClose.setEnabled(True)
|
|
425
|
+
msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Information, windowTitle="FlashGBX", text=text, standardButtons=QtWidgets.QMessageBox.Ok)
|
|
426
|
+
answer = msgbox.exec()
|
|
427
|
+
self.DEVICE = None
|
|
428
|
+
self.reject()
|
|
429
|
+
return True
|
|
430
|
+
elif ret == 2:
|
|
431
|
+
text = "The firmware update has failed. Please try again."
|
|
432
|
+
self.grpAvailableFwUpdates.setEnabled(True)
|
|
433
|
+
self.btnUpdate.setEnabled(True)
|
|
434
|
+
self.btnClose.setEnabled(True)
|
|
435
|
+
msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Critical, windowTitle="FlashGBX", text=text, standardButtons=QtWidgets.QMessageBox.Ok)
|
|
436
|
+
answer = msgbox.exec()
|
|
437
|
+
return False
|
|
438
|
+
elif ret == 3:
|
|
439
|
+
text = "The firmware update file is corrupted. Please re-install the application."
|
|
440
|
+
self.grpAvailableFwUpdates.setEnabled(True)
|
|
441
|
+
self.btnUpdate.setEnabled(True)
|
|
442
|
+
self.btnClose.setEnabled(True)
|
|
443
|
+
msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Critical, windowTitle="FlashGBX", text=text, standardButtons=QtWidgets.QMessageBox.Ok)
|
|
444
|
+
answer = msgbox.exec()
|
|
445
|
+
return False
|
|
446
|
+
elif ret == 4:
|
|
447
|
+
if platform.system() == 'Darwin':
|
|
448
|
+
self.SetStatus("No device found.", enableUI=True)
|
|
449
|
+
return False
|
|
450
|
+
answer = QtWidgets.QMessageBox.information(self, "FlashGBX", "If your Joey Jr device is currently running a Drag'n'Drop firmware, please continue and choose its <b>MODE.TXT</b> file.", QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel, QtWidgets.QMessageBox.Ok)
|
|
451
|
+
if answer == QtWidgets.QMessageBox.Cancel:
|
|
452
|
+
self.SetStatus("No device found.", enableUI=True)
|
|
453
|
+
return False
|
|
454
|
+
path = self.APP.SETTINGS.value("LastDirFirmwareUpdate")
|
|
455
|
+
path = QtWidgets.QFileDialog.getOpenFileName(self, "Choose the MODE.TXT file of your Joey Jr removable drive", path, "MODE.TXT (MODE*.TXT)")[0]
|
|
456
|
+
self.APP.QT_APP.processEvents()
|
|
457
|
+
if os.path.basename(path) not in ("MODE.TXT", "MODE!.TXT"):
|
|
458
|
+
self.SetStatus("No device found.", enableUI=True)
|
|
459
|
+
return False
|
|
460
|
+
self.APP.SETTINGS.setValue("LastDirFirmwareUpdate", os.path.dirname(path))
|
|
461
|
+
|
|
462
|
+
def SetStatus(self, text, enableUI=False, setProgress=None):
|
|
463
|
+
self.lblStatus.setText("Status: {:s}".format(text))
|
|
464
|
+
if setProgress is not None:
|
|
465
|
+
self.prgStatus.setValue(setProgress * 10)
|
|
466
|
+
if enableUI:
|
|
467
|
+
self.grpAvailableFwUpdates.setEnabled(True)
|
|
468
|
+
self.btnUpdate.setEnabled(True)
|
|
469
|
+
self.btnClose.setEnabled(True)
|
|
470
|
+
self.APP.QT_APP.processEvents()
|
|
471
|
+
except ImportError:
|
|
472
|
+
pass
|