FlashGBX 4.0.1__tar.gz → 4.2__tar.gz

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.
Files changed (53) hide show
  1. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/FlashGBX_GUI.py +12 -27
  2. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/GBMemory.py +35 -29
  3. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/LK_Device.py +37 -25
  4. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/Mapper.py +2 -57
  5. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/Util.py +3 -3
  6. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/fw_JoeyJr.py +35 -15
  7. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/hw_GBFlash.py +1 -1
  8. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/hw_GBxCartRW.py +8 -1
  9. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/hw_JoeyJr.py +1 -1
  10. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/res/config.zip +0 -0
  11. FlashGBX-4.2/FlashGBX/res/fw_GBFlash.zip +0 -0
  12. FlashGBX-4.2/FlashGBX/res/fw_GBxCart_RW_v1_4.zip +0 -0
  13. FlashGBX-4.2/FlashGBX/res/fw_GBxCart_RW_v1_4a.zip +0 -0
  14. FlashGBX-4.2/FlashGBX/res/fw_JoeyJr.zip +0 -0
  15. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX.egg-info/PKG-INFO +7 -6
  16. {FlashGBX-4.0.1 → FlashGBX-4.2}/PKG-INFO +7 -6
  17. {FlashGBX-4.0.1 → FlashGBX-4.2}/README.md +6 -5
  18. {FlashGBX-4.0.1 → FlashGBX-4.2}/setup.py +1 -1
  19. FlashGBX-4.0.1/FlashGBX/res/fw_GBFlash.zip +0 -0
  20. FlashGBX-4.0.1/FlashGBX/res/fw_GBxCart_RW_v1_4.zip +0 -0
  21. FlashGBX-4.0.1/FlashGBX/res/fw_GBxCart_RW_v1_4a.zip +0 -0
  22. FlashGBX-4.0.1/FlashGBX/res/fw_JoeyJr.zip +0 -0
  23. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/DataTransfer.py +0 -0
  24. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/FlashGBX.py +0 -0
  25. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/FlashGBX_CLI.py +0 -0
  26. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/Flashcart.py +0 -0
  27. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/PocketCamera.py +0 -0
  28. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/PocketCameraWindow.py +0 -0
  29. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/RomFileAGB.py +0 -0
  30. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/RomFileDMG.py +0 -0
  31. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/UserInputDialog.py +0 -0
  32. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/__init__.py +0 -0
  33. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/__main__.py +0 -0
  34. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/fw_GBFlash.py +0 -0
  35. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/fw_GBxCartRW_v1_3.py +0 -0
  36. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/fw_GBxCartRW_v1_4.py +0 -0
  37. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/pyside.py +0 -0
  38. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/res/Third Party Notices.md +0 -0
  39. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/res/fw_GBxCart_RW_Mini_v1_0.zip +0 -0
  40. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/res/fw_GBxCart_RW_XMAS_v1_0.zip +0 -0
  41. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/res/fw_GBxCart_RW_v1_1_v1_2.zip +0 -0
  42. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/res/fw_GBxCart_RW_v1_3.zip +0 -0
  43. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/res/icon.ico +0 -0
  44. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/res/icon.png +0 -0
  45. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX/res/pc_frame.png +0 -0
  46. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX.egg-info/SOURCES.txt +0 -0
  47. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX.egg-info/dependency_links.txt +0 -0
  48. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX.egg-info/entry_points.txt +0 -0
  49. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX.egg-info/requires.txt +0 -0
  50. {FlashGBX-4.0.1 → FlashGBX-4.2}/FlashGBX.egg-info/top_level.txt +0 -0
  51. {FlashGBX-4.0.1 → FlashGBX-4.2}/LICENSE +0 -0
  52. {FlashGBX-4.0.1 → FlashGBX-4.2}/MANIFEST.in +0 -0
  53. {FlashGBX-4.0.1 → FlashGBX-4.2}/setup.cfg +0 -0
@@ -183,22 +183,11 @@ class FlashGBX_GUI(QtWidgets.QWidget):
183
183
  self.layout_devices.addWidget(self.cmbDevice)
184
184
  self.layout_devices.addStretch()
185
185
 
186
- #btnText = "Too&ls"
187
- #self.btnTools = QtWidgets.QPushButton(btnText)
188
- #btnWidth = self.btnTools.fontMetrics().boundingRect(btnText).width() + 24
189
- #if platform.system() == "Darwin": btnWidth += 12
190
- #self.btnTools.setMaximumWidth(btnWidth)
191
186
  self.mnuTools = QtWidgets.QMenu("&Tools")
192
187
  self.mnuTools.addAction("Game Boy &Camera Album Viewer", self.ShowPocketCameraWindow)
193
188
  self.mnuTools.addSeparator()
194
189
  self.mnuTools.addAction("Firmware &Updater", self.ShowFirmwareUpdateWindow)
195
- #self.btnTools.setMenu(self.mnuTools)
196
190
 
197
- #btnText = "C&onfig"
198
- #self.btnConfig = QtWidgets.QPushButton(btnText)
199
- #btnWidth = self.btnConfig.fontMetrics().boundingRect(btnText).width() + 24
200
- #if platform.system() == "Darwin": btnWidth += 12
201
- #self.btnConfig.setMaximumWidth(btnWidth)
202
191
  self.mnuConfig = QtWidgets.QMenu("&Settings")
203
192
  self.mnuConfig.addAction("Check for &updates on application startup", lambda: [ self.EnableUpdateCheck() ])
204
193
  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")))
@@ -249,10 +238,10 @@ class FlashGBX_GUI(QtWidgets.QWidget):
249
238
  self.mnuConfig.actions()[7].setChecked(self.SETTINGS.value("UseNoIntroFilenames", default="enabled") == "enabled")
250
239
  self.mnuConfig.actions()[8].setChecked(self.SETTINGS.value("AutoPowerOff", default="350") != "0")
251
240
  self.mnuConfig.actions()[9].setChecked(self.SETTINGS.value("CompareSectors", default="enabled") == "enabled")
252
- #self.btnConfig.setMenu(self.mnuConfig)
253
241
 
254
242
  self.mnuThirdParty = QtWidgets.QMenu("Third Party &Notices")
255
243
  self.mnuThirdParty.addAction("About &Qt", lambda: [ QtWidgets.QMessageBox.aboutQt(None) ])
244
+ self.mnuThirdParty.addAction("About Game &Database", self.AboutGameDB)
256
245
  self.mnuThirdParty.addAction("Licenses", lambda: [ self.OpenPath(Util.APP_PATH + "/res/Third Party Notices.md") ])
257
246
 
258
247
  btnText = "&Options"
@@ -274,8 +263,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
274
263
  self.btnConnect = QtWidgets.QPushButton("&Connect")
275
264
  self.connect(self.btnConnect, QtCore.SIGNAL("clicked()"), self.ConnectDevice)
276
265
  self.layout_devices.addWidget(self.btnMainMenu)
277
- #self.layout_devices.addWidget(self.btnTools)
278
- #self.layout_devices.addWidget(self.btnConfig)
279
266
  self.layout_devices.addWidget(self.btnConnect)
280
267
 
281
268
  self.layout.addLayout(self.layout_devices, 1, 0, 1, 0)
@@ -355,12 +342,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
355
342
  lblDMGHeaderRtc.setContentsMargins(0, 1, 0, 1)
356
343
  rowDMGHeaderRtc.addWidget(lblDMGHeaderRtc)
357
344
  self.lblDMGHeaderRtcResult = QtWidgets.QLabel("")
358
- #self.lblDMGHeaderRtcResult.setCursor(QtGui.QCursor(QtCore.Qt.WhatsThisCursor))
359
- #self.lblDMGHeaderRtcResult.setToolTip("This shows the internal register values; in-game clock may use an offset")
360
- #self.lblDMGHeaderRtcResult.setStyleSheet("QLabel {{ color: {:s}; text-decoration: underline; cursor: hand; }}".format(QApplication.palette().color(QtGui.QPalette.Link).name()))
361
- #self.lblDMGHeaderRtcResult.setCursor(QtCore.Qt.PointingHandCursor)
362
- #self.connect(self.lblDMGHeaderRtcResult, QtCore.SIGNAL("clicked()"), self.EditRTC)
363
- #self.lblDMGHeaderRtcResult.clicked.connect(self.EditRTC)
364
345
  self.lblDMGHeaderRtcResult.mousePressEvent = lambda event: [ self.EditRTC(event) ]
365
346
  rowDMGHeaderRtc.addWidget(self.lblDMGHeaderRtcResult)
366
347
  rowDMGHeaderRtc.setStretch(0, 9)
@@ -475,8 +456,6 @@ class FlashGBX_GUI(QtWidgets.QWidget):
475
456
  lblAGBGpioRtc.setContentsMargins(0, 1, 0, 1)
476
457
  rowAGBGpioRtc.addWidget(lblAGBGpioRtc)
477
458
  self.lblAGBGpioRtcResult = QtWidgets.QLabel("")
478
- #self.lblAGBGpioRtcResult.setCursor(QtGui.QCursor(QtCore.Qt.WhatsThisCursor))
479
- #self.lblAGBGpioRtcResult.setToolTip(self.lblDMGHeaderRtcResult.toolTip())
480
459
  self.lblAGBGpioRtcResult.mousePressEvent = lambda event: [ self.EditRTC(event) ]
481
460
  rowAGBGpioRtc.addWidget(self.lblAGBGpioRtcResult)
482
461
  rowAGBGpioRtc.setStretch(0, 9)
@@ -731,7 +710,13 @@ class FlashGBX_GUI(QtWidgets.QWidget):
731
710
  msg = "This software is being developed by Lesserkuma as a hobby project. There is no affiliation with Nintendo or any other company. This software is provided as-is and the developer is not responsible for any damage that is caused by the use of it. Use at your own risk!<br><br>"
732
711
  msg += f"© 2020–{datetime.datetime.now().year} Lesserkuma<br>"
733
712
  msg += "• Website: <a href=\"https://github.com/lesserkuma/FlashGBX\">https://github.com/lesserkuma/FlashGBX</a><br><br>"
734
- msg += "Acknowledgments and Contributors:<br>2358, 90sFlav, AcoVanConis, AdmirtheSableye, AlexiG, ALXCO-Hardware, AndehX, antPL, aronson, Ausar, bbsan, BennVenn, ccs21, chobby, ClassicOldSong, Cliffback, 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, gandalf1980, 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, Lu, Luca DS, LucentW, manuelcm1, marv17, Merkin, metroid-maniac, Mr_V, olDirdey, orangeglo, paarongiroux, Paradoxical, Rairch, Raphaël BOICHOT, redalchemy, RetroGorek, RevZ, RibShark, s1cp, Satumox, Sgt.DoudouMiel, SH, Shinichi999, Sillyhatday, simonK, Sithdown, skite2001, Smelly-Ghost, Stitch, Super Maker, t5b6_de, Tauwasser, TheNFCookie, Timville, twitnic, velipso, Veund, voltagex, Voultar, Warez Waldo, wickawack, Winter1760, Wkr, x7l7j8cc, xactoes, xukkorz, yosoo, Zeii, Zelante, zipplet, Zoo, zvxr"
713
+ msg += "Acknowledgments and Contributors:<br>2358, 90sFlav, AcoVanConis, AdmirtheSableye, AlexiG, ALXCO-Hardware, AndehX, antPL, aronson, Ausar, bbsan, BennVenn, ccs21, chobby, ClassicOldSong, Cliffback, 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, gandalf1980, gboh, gekkio, Godan, Grender, HDR, Herax, Hiccup, hiks, howie0210, iamevn, Icesythe7, ide, inYourBackline, iyatemu, Jayro, Jenetrix, JFox, joyrider3774, jrharbort, JS7457, julgr, Kaede, kane159, KOOORAY, kscheel, kyokohunter, Leitplanke, litlemoran, LovelyA72, Lu, Luca DS, LucentW, manuelcm1, marv17, Merkin, metroid-maniac, Mr_V, olDirdey, orangeglo, paarongiroux, Paradoxical, Rairch, Raphaël BOICHOT, redalchemy, RetroGorek, RevZ, RibShark, s1cp, Satumox, Sgt.DoudouMiel, SH, Shinichi999, Sillyhatday, simonK, Sithdown, skite2001, Smelly-Ghost, Sonikks, Squiddy, Stitch, Super Maker, t5b6_de, Tauwasser, TheNFCookie, Timville, twitnic, velipso, Veund, voltagex, Voultar, Warez Waldo, wickawack, Winter1760, Wkr, x7l7j8cc, xactoes, xukkorz, yosoo, Zeii, Zelante, zipplet, Zoo, zvxr"
714
+ QtWidgets.QMessageBox.information(self, "{:s} {:s}".format(APPNAME, VERSION), msg, QtWidgets.QMessageBox.Ok)
715
+
716
+ def AboutGameDB(self):
717
+ msg = f"{APPNAME} uses a game database that is based on the ongoing efforts of the No-Intro project. Visit <a href=\"https://no-intro.org/\">https://no-intro.org/</a> for more information.<br><br>"
718
+ msg += f"No-Intro databases referenced for this version of {APPNAME}:<br>"
719
+ msg += "• Nintendo - Game Boy (20240713-090345)<br>• Nintendo - Game Boy Advance (20240803-104002)<br>• Nintendo - Game Boy Advance (Video) (20240727-194101)<br>• Nintendo - Game Boy Color (20240801-100010)" # No-Intro DBs
735
720
  QtWidgets.QMessageBox.information(self, "{:s} {:s}".format(APPNAME, VERSION), msg, QtWidgets.QMessageBox.Ok)
736
721
 
737
722
  def OpenPath(self, path=None):
@@ -926,7 +911,7 @@ class FlashGBX_GUI(QtWidgets.QWidget):
926
911
  qt_app.processEvents()
927
912
 
928
913
  messages = []
929
- last_msg = ""
914
+ #last_msg = ""
930
915
 
931
916
  # pylint: disable=global-variable-not-assigned
932
917
  global hw_devices
@@ -948,8 +933,8 @@ class FlashGBX_GUI(QtWidgets.QWidget):
948
933
  msg = ret[i][1]
949
934
  if msg in messages: # don’t show the same message twice
950
935
  continue
951
- else:
952
- last_msg = msg
936
+ #else:
937
+ # last_msg = msg
953
938
  if status == 3:
954
939
  messages.append(msg)
955
940
  self.CONN = None
@@ -961,7 +946,7 @@ class FlashGBX_GUI(QtWidgets.QWidget):
961
946
  if dev.IsConnected():
962
947
  self.DEVICES[dev.GetFullNameExtended()] = dev
963
948
  if dev.GetPort() in ports: break
964
-
949
+
965
950
  for dev in self.DEVICES.values():
966
951
  dev.Close()
967
952
 
@@ -118,24 +118,27 @@ class GBMemoryMap:
118
118
  else:
119
119
  rom_size = 0b101
120
120
 
121
- if info["rom_header"]["ram_size_raw"] not in Util.DMG_Header_RAM_Sizes_Map:
122
- sram_size = 0
123
- sram_type = 0b000
121
+ if mbc_type == 2:
122
+ sram_type = 0b010
124
123
  else:
125
- sram_size = Util.DMG_Header_RAM_Sizes_Flasher_Map[Util.DMG_Header_RAM_Sizes_Map.index(info["rom_header"]["ram_size_raw"])]
126
- if sram_size == 0:
124
+ if info["rom_header"]["ram_size_raw"] not in Util.DMG_Header_RAM_Sizes_Map:
125
+ sram_size = 0
127
126
  sram_type = 0b000
128
- elif sram_size == 0x2000:
129
- sram_type = 0b010
130
- elif sram_size == 0x8000:
131
- sram_type = 0b011
132
- elif sram_size == 0x10000:
133
- sram_type = 0b100
134
- elif sram_size == 0x20000:
135
- sram_type = 0b101
136
127
  else:
137
- sram_type = 0b000
138
-
128
+ sram_size = Util.DMG_Header_RAM_Sizes_Flasher_Map[Util.DMG_Header_RAM_Sizes_Map.index(info["rom_header"]["ram_size_raw"])]
129
+ if sram_size == 0:
130
+ sram_type = 0b000
131
+ elif sram_size == 0x2000:
132
+ sram_type = 0b010
133
+ elif sram_size == 0x8000:
134
+ sram_type = 0b011
135
+ elif sram_size == 0x10000:
136
+ sram_type = 0b100
137
+ elif sram_size == 0x20000:
138
+ sram_type = 0b101
139
+ else:
140
+ sram_type = 0b000
141
+
139
142
  info["map"] = {
140
143
  "mbc_type":mbc_type,
141
144
  "rom_size":rom_size,
@@ -236,23 +239,26 @@ class GBMemoryMap:
236
239
  else:
237
240
  rom_size = 0b101
238
241
 
239
- if info["rom_header"]["game_title"] == "NP M-MENU MENU" or info["rom_header"]["ram_size_raw"] not in Util.DMG_Header_RAM_Sizes_Map:
240
- sram_size = 0
241
- sram_type = 0b000
242
+ if mbc_type == 2:
243
+ sram_type = 0b010
242
244
  else:
243
- sram_size = Util.DMG_Header_RAM_Sizes_Flasher_Map[Util.DMG_Header_RAM_Sizes_Map.index(info["rom_header"]["ram_size_raw"])]
244
- if sram_size == 0:
245
+ if info["rom_header"]["game_title"] == "NP M-MENU MENU" or info["rom_header"]["ram_size_raw"] not in Util.DMG_Header_RAM_Sizes_Map:
246
+ sram_size = 0
245
247
  sram_type = 0b000
246
- elif sram_size == 0x2000:
247
- sram_type = 0b010
248
- elif sram_size == 0x8000:
249
- sram_type = 0b011
250
- elif sram_size == 0x10000:
251
- sram_type = 0b100
252
- elif sram_size == 0x20000:
253
- sram_type = 0b101
254
248
  else:
255
- sram_type = 0b000
249
+ sram_size = Util.DMG_Header_RAM_Sizes_Flasher_Map[Util.DMG_Header_RAM_Sizes_Map.index(info["rom_header"]["ram_size_raw"])]
250
+ if sram_size == 0:
251
+ sram_type = 0b000
252
+ elif sram_size == 0x2000:
253
+ sram_type = 0b010
254
+ elif sram_size == 0x8000:
255
+ sram_type = 0b011
256
+ elif sram_size == 0x10000:
257
+ sram_type = 0b100
258
+ elif sram_size == 0x20000:
259
+ sram_type = 0b101
260
+ else:
261
+ sram_type = 0b000
256
262
 
257
263
  info["map"] = {
258
264
  "mbc_type":mbc_type,
@@ -420,14 +420,16 @@ class LK_Device(ABC):
420
420
  retries -= 1
421
421
  dprint("Retries left:", retries)
422
422
 
423
- hp = 10
423
+ hp = 20
424
424
  temp = 0
425
425
  while temp not in (1, 2) and hp > 0:
426
+ self.DEVICE.reset_output_buffer()
427
+ self.DEVICE.reset_input_buffer()
426
428
  self.DEVICE.write(b'\x00')
427
429
  temp = self._read(1)
428
- dprint("Current response:", temp)
429
430
  hp -= 1
430
- if hp == 0: break
431
+ dprint("Current response:", temp, ", HP:", hp)
432
+ #if hp == 0: break
431
433
  return False
432
434
 
433
435
  def _write(self, data, wait=False):
@@ -533,9 +535,9 @@ class LK_Device(ABC):
533
535
  buffer.extend(struct.pack(">I", value))
534
536
 
535
537
  if self.FW["fw_ver"] >= 12:
536
- self._try_write(buffer)
538
+ return self._try_write(buffer)
537
539
  else:
538
- self._write(buffer)
540
+ return self._write(buffer)
539
541
 
540
542
  def _cart_read(self, address, length=0, agb_save_flash=False):
541
543
  if self.MODE == "DMG":
@@ -870,7 +872,8 @@ class LK_Device(ABC):
870
872
  self.SIGNAL = None
871
873
 
872
874
  def Debug(self):
873
- # self.SetPin(["PIN_AUDIO"], True)
875
+ # for i in range(0, 0x100000):
876
+ # print(hex(i), self._set_fw_variable("ADDRESS", i), end="\r", flush=True)
874
877
  return
875
878
 
876
879
  def ReadInfo(self, setPinsAsInputs=False, checkRtc=True):
@@ -2180,22 +2183,26 @@ class LK_Device(ABC):
2180
2183
 
2181
2184
  if ".dev" in Util.VERSION_PEP440 or Util.DEBUG:
2182
2185
  with open("debug_cfi.bin", "wb") as f: f.write(cfi_buffer)
2183
- magic = "{:s}{:s}{:s}".format(chr(cfi_buffer[0x20]), chr(cfi_buffer[0x22]), chr(cfi_buffer[0x24]))
2184
- d_swap = (0, 0)
2185
- if magic == "QRY": # D0D1 not swapped
2186
- pass
2187
- elif magic == "RQZ": # D0D1 swapped
2188
- d_swap = [(0, 1)]
2189
- for j2 in range(0, len(d_swap)):
2190
- for j in range(0, len(cfi_buffer)):
2191
- cfi_buffer[j] = bitswap(cfi_buffer[j], d_swap[j2])
2192
- elif magic == "\x92\x91\x9A": # D0D1+D6D7 swapped
2193
- d_swap = [( 0, 1 ), ( 6, 7 )]
2194
- for j2 in range(0, len(d_swap)):
2195
- for j in range(0, len(cfi_buffer)):
2196
- cfi_buffer[j] = bitswap(cfi_buffer[j], d_swap[j2])
2197
- with open("debug_cfi_2.bin", "wb") as f: f.write(cfi_buffer)
2198
- else:
2186
+ try:
2187
+ magic = "{:s}{:s}{:s}".format(chr(cfi_buffer[0x20]), chr(cfi_buffer[0x22]), chr(cfi_buffer[0x24]))
2188
+ d_swap = (0, 0)
2189
+ if magic == "QRY": # D0D1 not swapped
2190
+ pass
2191
+ elif magic == "RQZ": # D0D1 swapped
2192
+ d_swap = [(0, 1)]
2193
+ for j2 in range(0, len(d_swap)):
2194
+ for j in range(0, len(cfi_buffer)):
2195
+ cfi_buffer[j] = bitswap(cfi_buffer[j], d_swap[j2])
2196
+ elif magic == "\x92\x91\x9A": # D0D1+D6D7 swapped
2197
+ d_swap = [( 0, 1 ), ( 6, 7 )]
2198
+ for j2 in range(0, len(d_swap)):
2199
+ for j in range(0, len(cfi_buffer)):
2200
+ cfi_buffer[j] = bitswap(cfi_buffer[j], d_swap[j2])
2201
+ if ".dev" in Util.VERSION_PEP440 or Util.DEBUG:
2202
+ with open("debug_cfi_d0d1+d6d7.bin", "wb") as f: f.write(cfi_buffer)
2203
+ else:
2204
+ cfi_buffer = None
2205
+ except:
2199
2206
  cfi_buffer = None
2200
2207
 
2201
2208
  if self.MODE == "DMG":
@@ -3333,6 +3340,8 @@ class LK_Device(ABC):
3333
3340
  rtc_buffer = self._read(8)
3334
3341
  if len(rtc_buffer) == 8 and _agb_gpio.HasRTC(rtc_buffer) is True:
3335
3342
  rtc_buffer = rtc_buffer[1:]
3343
+ rtc_buffer.append(_agb_gpio.RTCReadStatus()) # 24h mode = 0x40, reset flag = 0x80
3344
+ rtc_buffer.extend(struct.pack("<Q", int(time.time())))
3336
3345
  else:
3337
3346
  rtc_buffer = None
3338
3347
  else:
@@ -3547,6 +3556,9 @@ class LK_Device(ABC):
3547
3556
  if (self.FW["fw_ver"] < 12 and "set_irq_high" in cart_type and cart_type["set_irq_high"] is True):
3548
3557
  self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge type requires at least firmware version L12.", "abortable":False})
3549
3558
  return False
3559
+ if (self.FW["fw_ver"] < 12 and "status_register_mask" in cart_type):
3560
+ self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge type requires at least firmware version L12.", "abortable":False})
3561
+ return False
3550
3562
  # Firmware check L12
3551
3563
 
3552
3564
  # Ensure cart is powered
@@ -3781,6 +3793,7 @@ class LK_Device(ABC):
3781
3793
  self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge type is currently not supported for ROM writing.", "abortable":False})
3782
3794
  return False
3783
3795
 
3796
+ we = 0x00
3784
3797
  if flashcart.WEisWR():
3785
3798
  we = 0x01 # FLASH_WE_PIN_WR
3786
3799
  self._write(we)
@@ -3794,7 +3807,6 @@ class LK_Device(ABC):
3794
3807
  self._write(we) # FLASH_WE_PIN_WR_RESET
3795
3808
  dprint("Using WR+RESET as WE")
3796
3809
  else:
3797
- we = 0x00
3798
3810
  self._write(we) # unset
3799
3811
 
3800
3812
  for i in range(0, 6):
@@ -4107,7 +4119,7 @@ class LK_Device(ABC):
4107
4119
  len_rest = end_address - pos
4108
4120
  skip_se = False
4109
4121
  ts_se_start = time.time()
4110
- if "compare_sectors" in args and args["compare_sectors"] is True and sector[1] <= len_rest and not (flashcart and cart_type["command_set"] == "GBAMP"):
4122
+ if self.FW["fw_ver"] >= 12 and "compare_sectors" in args and args["compare_sectors"] is True and sector[1] <= len_rest and not (flashcart and cart_type["command_set"] == "GBAMP"):
4111
4123
  verified = self.CompareCRC32(buffer=data_import, offset=sector[0], length=sector[1], address=start_address, flashcart=flashcart, reset=True)
4112
4124
  if verified is True:
4113
4125
  skip_se = True
@@ -4387,7 +4399,7 @@ class LK_Device(ABC):
4387
4399
  dprint(f"Verifying ROM bank #{bank} at 0x{pos_from:x} (physical 0x{start_address:X}, 0x{verify_len:X} bytes)")
4388
4400
 
4389
4401
  verified = False
4390
- if sector[1] >= verify_len and crc32_errors < 5:
4402
+ if self.FW["fw_ver"] >= 12 and sector[1] >= verify_len and crc32_errors < 5:
4391
4403
  verified = self.CompareCRC32(buffer=data_import, offset=pos_from, length=verify_len, address=start_address, flashcart=flashcart, reset=False)
4392
4404
  if verified is True:
4393
4405
  dprint("CRC32 verification successful between 0x{:X} and 0x{:X}".format(pos_from, verify_len))
@@ -404,8 +404,6 @@ class DMG_MBC3(DMG_MBC):
404
404
  seconds = dt_new.second
405
405
  minutes = dt_new.minute
406
406
  hours = dt_new.hour
407
- #temp = dt_new - dt_buffer1
408
- #days = temp.days
409
407
  temp = datetime.date.fromtimestamp(timestamp_now) - datetime.date.fromtimestamp(timestamp_then)
410
408
  days = temp.days + days
411
409
  if days >= 512:
@@ -413,13 +411,6 @@ class DMG_MBC3(DMG_MBC):
413
411
  days = days % 512
414
412
  dprint(seconds, minutes, hours, days, carry)
415
413
 
416
- #buffer[0x00] = seconds % 60
417
- #buffer[0x04] = minutes % 60
418
- #buffer[0x08] = hours % 24
419
- #buffer[0x0C] = days & 0xFF
420
- #buffer[0x10] = days >> 8 & 0x1
421
- #if carry:
422
- # buffer[0x10] |= 0x80
423
414
  except Exception as e:
424
415
  print("Couldn’t update the RTC register values\n", e)
425
416
 
@@ -1065,15 +1056,10 @@ class DMG_HuC3(DMG_MBC):
1065
1056
  dprint(dt_then, dt_now, dt_buffer1, dt_buffer2, dt_new, sep="\n")
1066
1057
  minutes = dt_new.minute
1067
1058
  hours = dt_new.hour
1068
- #temp = dt_new - dt_buffer1
1069
- #days = temp.days
1070
1059
  temp = datetime.date.fromtimestamp(timestamp_now) - datetime.date.fromtimestamp(timestamp_then)
1071
1060
  days = temp.days + days
1072
1061
  dprint(minutes, hours, days)
1073
1062
 
1074
- #total_minutes = 60 * hours + minutes
1075
- #data = (total_minutes & 0xFFF) | ((days & 0xFFF) << 12)
1076
- #buffer[0:4] = struct.pack("<I", data)
1077
1063
  d = {
1078
1064
  "rtc_h":hours,
1079
1065
  "rtc_m":minutes,
@@ -1322,23 +1308,8 @@ class DMG_TAMA5(DMG_MBC):
1322
1308
  dt_new_notime = dt_new.replace(hour=0, minute=0, second=0)
1323
1309
  days_passed = int((dt_new_notime.timestamp() - dt_buffer_notime.timestamp()) / 60 / 60 / 24)
1324
1310
  weekday += days_passed % 7
1325
- #print("leap_year_state#1", leap_year_state)
1326
1311
  leap_year_state = (leap_year_state + year_new) % 4
1327
- #print("leap_year_state#2", leap_year_state)
1328
- #print("New:", seconds, minutes, hours, day_of_week, days, months, years, leap_year_state, z24h_flag)
1329
-
1330
- # buffer[0x00] = Util.EncodeBCD(seconds)
1331
- # buffer[0x01] = Util.EncodeBCD(minutes)
1332
- # buffer[0x02] = Util.EncodeBCD(hours)
1333
- # buffer[0x03] = (weekday & 0xF) | ((Util.EncodeBCD(days) & 0xF) << 4)
1334
- # buffer[0x04] = (Util.EncodeBCD(days) >> 4) | ((Util.EncodeBCD(months) & 0xF) << 4)
1335
- # buffer[0x05] = (Util.EncodeBCD(months) >> 4) | ((Util.EncodeBCD(years) & 0xF) << 4)
1336
- # buffer[0x06] = (Util.EncodeBCD(years) >> 4)
1337
- # buffer[0x0D] = leap_year_state << 4 | z24h_flag
1338
-
1339
- #dstr = ' '.join(format(x, '02X') for x in buffer)
1340
- #print("[{:02X}] {:s}".format(int(len(dstr)/3) + 1, dstr))
1341
-
1312
+
1342
1313
  except Exception as e:
1343
1314
  print("Couldn’t update the RTC register values\n", e)
1344
1315
 
@@ -1560,31 +1531,6 @@ class DMG_Unlicensed_DatelOrbitV2(DMG_MBC):
1560
1531
  def GetMaxROMSize(self):
1561
1532
  return 128*1024
1562
1533
 
1563
- # class DMG_Unlicensed_DatelMegaMem(DMG_MBC):
1564
- # def GetName(self):
1565
- # return "Datel MegaMem"
1566
-
1567
- # def __init__(self, args=None, cart_write_fncptr=None, cart_read_fncptr=None, cart_powercycle_fncptr=None, clk_toggle_fncptr=None):
1568
- # if args is None: args = {}
1569
- # super().__init__(args=args, cart_write_fncptr=cart_write_fncptr, cart_read_fncptr=cart_read_fncptr, cart_powercycle_fncptr=cart_powercycle_fncptr, clk_toggle_fncptr=None)
1570
- # self.ROM_BANK_SIZE = 0x4000
1571
- # self.RAM_BANK_SIZE = 0x4000
1572
-
1573
- # def SelectBankROM(self, index):
1574
- # dprint(self.GetName(), "|", index)
1575
- # return (0, self.ROM_BANK_SIZE)
1576
-
1577
- # def SelectBankRAM(self, index):
1578
- # dprint(self.GetName(), "|", index)
1579
- # self.CartWrite([[ 0x2000, index & 0x20 ]])
1580
- # return (0x4000, self.RAM_BANK_SIZE)
1581
-
1582
- # def GetROMBanks(self, rom_size):
1583
- # return 1
1584
-
1585
- # def GetMaxROMSize(self):
1586
- # return 16*1024
1587
-
1588
1534
 
1589
1535
  class AGB_GPIO:
1590
1536
  CART_WRITE_FNCPTR = None
@@ -1769,9 +1715,8 @@ class AGB_GPIO:
1769
1715
  ])
1770
1716
 
1771
1717
  # Add timestamp of backup time
1772
- ts = int(time.time())
1773
1718
  buffer.append(self.RTCReadStatus()) # 24h mode = 0x40, reset flag = 0x80
1774
- buffer.extend(struct.pack("<Q", ts))
1719
+ buffer.extend(struct.pack("<Q", int(time.time())))
1775
1720
 
1776
1721
  dprint(' '.join(format(x, '02X') for x in buffer))
1777
1722
 
@@ -8,9 +8,9 @@ from enum import Enum
8
8
 
9
9
  # Common constants
10
10
  APPNAME = "FlashGBX"
11
- VERSION_PEP440 = "4.0.1"
11
+ VERSION_PEP440 = "4.2"
12
12
  VERSION = "v{:s}".format(VERSION_PEP440)
13
- VERSION_TIMESTAMP = 1719742346
13
+ VERSION_TIMESTAMP = 1722797669
14
14
  DEBUG = False
15
15
  DEBUG_LOG = []
16
16
  APP_PATH = ""
@@ -410,7 +410,7 @@ def ParseCFI(buffer):
410
410
  info["magic"] = "{:s}{:s}{:s}".format(chr(buffer[0x20]), chr(buffer[0x22]), chr(buffer[0x24]))
411
411
 
412
412
  if buffer[0x36] == 0xFF and buffer[0x48] == 0xFF:
413
- print("FAIL: No information about the voltage range found in CFI data.")
413
+ print("Note: Invalid values found in Common Flash Interface data.")
414
414
  try:
415
415
  with open("./cfi_debug.bin", "wb") as f: f.write(buffer)
416
416
  except:
@@ -32,31 +32,39 @@ class FirmwareUpdater():
32
32
 
33
33
  with open(file, "rb") as f: temp = f.read().decode("UTF-8", "ignore")
34
34
  if not temp.startswith("UPDATE"):
35
- with open(file, "w", encoding="UTF-8") as f: f.write("UPDATE\r\n")
35
+ with open(file, "wb") as f:
36
+ temp = bytearray(b"UPDATE")
37
+ temp += bytearray([0] * (256 - len(temp)))
38
+ f.write(temp)
36
39
  hp = 30
37
40
  while hp > 0:
38
41
  if os.path.exists(path + "FIRMWARE.JR"): break
39
42
  time.sleep(1)
40
43
  hp -= 1
41
44
  if hp == 0:
42
- fncSetStatus(text="Error: Couldn’t communicate with the Joey Jr device.")
45
+ fncSetStatus(text="Couldn’t communicate with the Joey Jr device.")
43
46
  return 2
44
47
 
45
- with open(file, "rb") as f: temp = f.read().decode("UTF-8", "ignore")
48
+ try:
49
+ with open(file, "rb") as f: temp = f.read().decode("UTF-8", "ignore")
50
+ except FileNotFoundError:
51
+ fncSetStatus(text="Couldn’t access MODE.TXT. Remove cartridge and try again.")
52
+ return 2
53
+
46
54
  if not temp.startswith("UPDATE"):
47
- fncSetStatus(text="Error: Couldn’t enter UPDATE mode, please try again.")
55
+ fncSetStatus(text="Couldn’t enter UPDATE mode, please try again.")
48
56
  return 2
49
57
 
50
58
  fncSetStatus(text="Updating firmware... Do not unplug the device!", setProgress=0)
51
59
  os.unlink(path + "FIRMWARE.JR")
52
60
  if os.path.exists(path + "FIRMWARE.JR"):
53
- fncSetStatus(text="Error: Couldn’t write new firmware, please try again.")
61
+ fncSetStatus(text="Couldn’t write new firmware, please try again.")
54
62
  return 2
55
63
 
56
64
  try:
57
65
  f = open(path + "FIRMWARE.JR", "wb")
58
66
  except OSError:
59
- fncSetStatus(text="Error: Couldn’t write new firmware, please try again.")
67
+ fncSetStatus(text="Couldn’t write new firmware, please try again.")
60
68
  return 2
61
69
 
62
70
  for i in range(0, len(buffer), 64):
@@ -69,9 +77,18 @@ class FirmwareUpdater():
69
77
  except OSError:
70
78
  pass
71
79
 
72
- time.sleep(3)
80
+ if b"Joey Jr. Firmware" not in buffer:
81
+ hp = 5
82
+ while hp > 0:
83
+ if not os.path.exists(path + "FIRMWARE.JR"): break
84
+ time.sleep(1)
85
+ hp -= 1
86
+ if hp == 0:
87
+ fncSetStatus(text="Couldn’t verify, please try again.")
88
+ return 2
89
+
73
90
  fncSetStatus("Done.")
74
- time.sleep(1)
91
+ time.sleep(2)
75
92
 
76
93
  return True
77
94
 
@@ -141,16 +158,16 @@ class FirmwareUpdater():
141
158
  pass
142
159
  elif counter + 64 < size:
143
160
  print("\nBad response at", counter)
144
- fncSetStatus(text="Error: Bad response at 0x{:X}!".format(counter), setProgress=percent)
161
+ fncSetStatus(text="Error! Bad response at 0x{:X}!".format(counter), setProgress=percent)
145
162
  return 2
146
163
 
147
164
  counter += 64
148
165
  fncSetStatus(text="Updating firmware... Do not unplug the device!", setProgress=percent)
149
166
 
150
167
  dev.close()
151
- time.sleep(0.8)
152
- fncSetStatus("Done.", setProgress=100)
153
168
  time.sleep(1)
169
+ fncSetStatus("Done.", setProgress=100)
170
+ time.sleep(2)
154
171
  return 1
155
172
 
156
173
  try:
@@ -302,9 +319,9 @@ try:
302
319
  self.lblDeviceNameResult.setText(self.DEV_NAME + " " + self.PCB_VER)
303
320
  self.lblDeviceFWVerResult.setText(self.FW_VER)
304
321
 
305
- if platform.system() == 'Darwin':
306
- self.optFW_MSC.setVisible(False)
307
- self.lblFW_MSC_Blerb.setVisible(False)
322
+ # if platform.system() == 'Darwin':
323
+ # self.optFW_MSC.setVisible(False)
324
+ # self.lblFW_MSC_Blerb.setVisible(False)
308
325
 
309
326
  def run(self):
310
327
  try:
@@ -446,8 +463,11 @@ try:
446
463
  elif ret == 4:
447
464
  if platform.system() == 'Darwin':
448
465
  self.SetStatus("No device found.", enableUI=True)
466
+ text = "If your Joey Jr device is currently running the Drag'n'Drop firmware, please update the firmware on Windows or Linux, or use the standalone firmware updater."
467
+ msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Critical, windowTitle="FlashGBX", text=text, standardButtons=QtWidgets.QMessageBox.Ok)
468
+ answer = msgbox.exec()
449
469
  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)
470
+ answer = QtWidgets.QMessageBox.information(self, "FlashGBX", "If your Joey Jr device is currently running the Drag'n'Drop firmware, please continue and choose its <b>MODE.TXT</b> file.", QtWidgets.QMessageBox.Ok | QtWidgets.QMessageBox.Cancel, QtWidgets.QMessageBox.Ok)
451
471
  if answer == QtWidgets.QMessageBox.Cancel:
452
472
  self.SetStatus("No device found.", enableUI=True)
453
473
  return False
@@ -9,7 +9,7 @@ class GbxDevice(LK_Device):
9
9
  DEVICE_NAME = "GBFlash"
10
10
  DEVICE_MIN_FW = 1
11
11
  DEVICE_MAX_FW = 12
12
- DEVICE_LATEST_FW_TS = { 5:1719609931, 10:1719609931, 11:1719609931, 12:1719609931, 13:1719609931 }
12
+ DEVICE_LATEST_FW_TS = { 5:1722774120, 10:1722774120, 11:1722774120, 12:1722774120, 13:1722774120 }
13
13
  PCB_VERSIONS = { 5:'', 12:'v1.2', 13:'v1.3' }
14
14
 
15
15
  def __init__(self):
@@ -9,7 +9,7 @@ class GbxDevice(LK_Device):
9
9
  DEVICE_NAME = "GBxCart RW"
10
10
  DEVICE_MIN_FW = 1
11
11
  DEVICE_MAX_FW = 1
12
- DEVICE_LATEST_FW_TS = { 4:1709317610, 5:1719609931, 6:1719609931, 2:0, 90:0, 100:0 }
12
+ DEVICE_LATEST_FW_TS = { 4:1709317610, 5:1722774120, 6:1722774120, 2:0, 90:0, 100:0 }
13
13
  PCB_VERSIONS = { 5:'v1.4', 6:'v1.4a/b/c', 2:'v1.1/v1.2', 4:'v1.3', 90:'XMAS v1.0', 100:'Mini v1.0' }
14
14
  BAUDRATE = 1000000
15
15
  MAX_BUFFER_READ = 0x1000
@@ -74,6 +74,8 @@ class GbxDevice(LK_Device):
74
74
  self.MAX_BUFFER_WRITE = 0x100
75
75
 
76
76
  conn_msg.append([0, "For help with your GBxCart RW device, please visit the insideGadgets Discord: https://gbxcart.com/discord"])
77
+ if self.FW["pcb_ver"] == 4:
78
+ conn_msg.append([0, "Note: Your GBxCart RW hardware revision does not fully support the latest features due to technical limitations. Please consider upgrading to a newer device."])
77
79
 
78
80
  self.PORT = ports[i]
79
81
  self.DEVICE.timeout = self.DEVICE_TIMEOUT
@@ -320,3 +322,8 @@ class GbxDevice(LK_Device):
320
322
  except SerialException:
321
323
  pass
322
324
  return super().Close(cartPowerOff)
325
+
326
+ def SetTimeout(self, seconds=1):
327
+ if seconds < 1: seconds = 1
328
+ self.DEVICE_TIMEOUT = seconds
329
+ self.DEVICE.timeout = self.DEVICE_TIMEOUT
@@ -9,7 +9,7 @@ class GbxDevice(LK_Device):
9
9
  DEVICE_NAME = "Joey Jr"
10
10
  DEVICE_MIN_FW = 1
11
11
  DEVICE_MAX_FW = 12
12
- DEVICE_LATEST_FW_TS = 1719609931
12
+ DEVICE_LATEST_FW_TS = 1722774120
13
13
  PCB_VERSIONS = { -1:"", 0x01:"V2", 0x81:"V2", 0x02:"V2C", 0x82:"V2C", 0x03:"V2CC", 0x83:"V2CC/V2++" }
14
14
 
15
15
  def __init__(self):
Binary file
Binary file
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: FlashGBX
3
- Version: 4.0.1
3
+ Version: 4.2
4
4
  Summary: Reads and writes Game Boy and Game Boy Advance cartridge data
5
5
  Home-page: https://github.com/lesserkuma/FlashGBX
6
6
  Author: Lesserkuma
@@ -147,7 +147,7 @@ Use this command in a Terminal or Command Prompt window to launch the installed
147
147
  - DIY cart with MX29F040
148
148
  - DIY cart with MX29LV640
149
149
  - DIY cart with SST39SF040
150
- - DMG-MBC5-32M-FLASH Development Cartridge, E201264
150
+ - DMG-MBC5-32M-FLASH (G/A) Development Cartridge, E201264
151
151
  - Ferrante Crafts cart 32 KB
152
152
  - Ferrante Crafts cart 64 KB
153
153
  - Ferrante Crafts cart 512 KB
@@ -175,8 +175,9 @@ Use this command in a Terminal or Command Prompt window to launch the installed
175
175
  - Game Boy Advance
176
176
 
177
177
  - Action Replay Ultimate Codes (with SST39VF800A)
178
- - Development AGB Cartridge 64M Flash, E201629
179
- - Development AGB Cartridge 64M Flash S, E201843
178
+ - Development AGB Cartridge 64M Flash, E201629¹
179
+ - Development AGB Cartridge 64M Flash, E201629 (128M, with 4× LH28F320BJE)¹
180
+ - Development AGB Cartridge 64M Flash S, E201843¹
180
181
  - Development AGB Cartridge 128M Flash S, E201850
181
182
  - Development AGB Cartridge 256M Flash S, E201868
182
183
  - DL9SEC GBA flashcart with TE28F128
@@ -326,7 +327,7 @@ Use this command in a Terminal or Command Prompt window to launch the installed
326
327
  - GA-07 with unlabeled flash chip
327
328
  - GE28F128W30 with 128W30B0
328
329
  - K5L2BX_32D_16D_V2 with K5L2833ATA
329
- - M36XXX_32A_EARTH with M36L0R8060B
330
+ - M36XXX_32A_EARTH with M36L0R806
330
331
  - M36XXX_T32_32D_16D with M36L0R806
331
332
  - M5M29-39VF512 with M5M29HD528
332
333
  - M5M29G130AN (no PCB text)
@@ -370,7 +371,7 @@ Many different reproduction cartridges share their flash chip command set, so ev
370
371
 
371
372
  The author would like to thank the following very kind people for their help, contributions or documentation (in alphabetical order):
372
373
 
373
- 2358, 90sFlav, AcoVanConis, AdmirtheSableye, AlexiG, ALXCO-Hardware, AndehX, antPL, aronson, Ausar, bbsan, BennVenn, ccs21, chobby, ClassicOldSong, Cliffback, 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, gandalf1980, 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, Lu, Luca DS, LucentW, manuelcm1, marv17, Merkin, metroid-maniac, Mr_V, olDirdey, orangeglo, paarongiroux, Paradoxical, Rairch, Raphaël BOICHOT, redalchemy, RetroGorek, RevZ, RibShark, s1cp, Satumox, Sgt.DoudouMiel, SH, Shinichi999, Sillyhatday, simonK, Sithdown, skite2001, Smelly-Ghost, Stitch, Super Maker, t5b6_de, Tauwasser, TheNFCookie, Timville, twitnic, velipso, Veund, voltagex, Voultar, Warez Waldo, wickawack, Winter1760, Wkr, x7l7j8cc, xactoes, xukkorz, yosoo, Zeii, Zelante, zipplet, Zoo, zvxr
374
+ 2358, 90sFlav, AcoVanConis, AdmirtheSableye, AlexiG, ALXCO-Hardware, AndehX, antPL, aronson, Ausar, bbsan, BennVenn, ccs21, chobby, ClassicOldSong, Cliffback, 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, gandalf1980, gboh, gekkio, Godan, Grender, HDR, Herax, Hiccup, hiks, howie0210, iamevn, Icesythe7, ide, inYourBackline, iyatemu, Jayro, Jenetrix, JFox, joyrider3774, jrharbort, JS7457, julgr, Kaede, kane159, KOOORAY, kscheel, kyokohunter, Leitplanke, litlemoran, LovelyA72, Lu, Luca DS, LucentW, manuelcm1, marv17, Merkin, metroid-maniac, Mr_V, olDirdey, orangeglo, paarongiroux, Paradoxical, Rairch, Raphaël BOICHOT, redalchemy, RetroGorek, RevZ, RibShark, s1cp, Satumox, Sgt.DoudouMiel, SH, Shinichi999, Sillyhatday, simonK, Sithdown, skite2001, Smelly-Ghost, Sonikks, Squiddy, Stitch, Super Maker, t5b6_de, Tauwasser, TheNFCookie, Timville, twitnic, velipso, Veund, voltagex, Voultar, Warez Waldo, wickawack, Winter1760, Wkr, x7l7j8cc, xactoes, xukkorz, yosoo, Zeii, Zelante, zipplet, Zoo, zvxr
374
375
 
375
376
  ## Third Party Notices and Licenses
376
377
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: FlashGBX
3
- Version: 4.0.1
3
+ Version: 4.2
4
4
  Summary: Reads and writes Game Boy and Game Boy Advance cartridge data
5
5
  Home-page: https://github.com/lesserkuma/FlashGBX
6
6
  Author: Lesserkuma
@@ -147,7 +147,7 @@ Use this command in a Terminal or Command Prompt window to launch the installed
147
147
  - DIY cart with MX29F040
148
148
  - DIY cart with MX29LV640
149
149
  - DIY cart with SST39SF040
150
- - DMG-MBC5-32M-FLASH Development Cartridge, E201264
150
+ - DMG-MBC5-32M-FLASH (G/A) Development Cartridge, E201264
151
151
  - Ferrante Crafts cart 32 KB
152
152
  - Ferrante Crafts cart 64 KB
153
153
  - Ferrante Crafts cart 512 KB
@@ -175,8 +175,9 @@ Use this command in a Terminal or Command Prompt window to launch the installed
175
175
  - Game Boy Advance
176
176
 
177
177
  - Action Replay Ultimate Codes (with SST39VF800A)
178
- - Development AGB Cartridge 64M Flash, E201629
179
- - Development AGB Cartridge 64M Flash S, E201843
178
+ - Development AGB Cartridge 64M Flash, E201629¹
179
+ - Development AGB Cartridge 64M Flash, E201629 (128M, with 4× LH28F320BJE)¹
180
+ - Development AGB Cartridge 64M Flash S, E201843¹
180
181
  - Development AGB Cartridge 128M Flash S, E201850
181
182
  - Development AGB Cartridge 256M Flash S, E201868
182
183
  - DL9SEC GBA flashcart with TE28F128
@@ -326,7 +327,7 @@ Use this command in a Terminal or Command Prompt window to launch the installed
326
327
  - GA-07 with unlabeled flash chip
327
328
  - GE28F128W30 with 128W30B0
328
329
  - K5L2BX_32D_16D_V2 with K5L2833ATA
329
- - M36XXX_32A_EARTH with M36L0R8060B
330
+ - M36XXX_32A_EARTH with M36L0R806
330
331
  - M36XXX_T32_32D_16D with M36L0R806
331
332
  - M5M29-39VF512 with M5M29HD528
332
333
  - M5M29G130AN (no PCB text)
@@ -370,7 +371,7 @@ Many different reproduction cartridges share their flash chip command set, so ev
370
371
 
371
372
  The author would like to thank the following very kind people for their help, contributions or documentation (in alphabetical order):
372
373
 
373
- 2358, 90sFlav, AcoVanConis, AdmirtheSableye, AlexiG, ALXCO-Hardware, AndehX, antPL, aronson, Ausar, bbsan, BennVenn, ccs21, chobby, ClassicOldSong, Cliffback, 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, gandalf1980, 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, Lu, Luca DS, LucentW, manuelcm1, marv17, Merkin, metroid-maniac, Mr_V, olDirdey, orangeglo, paarongiroux, Paradoxical, Rairch, Raphaël BOICHOT, redalchemy, RetroGorek, RevZ, RibShark, s1cp, Satumox, Sgt.DoudouMiel, SH, Shinichi999, Sillyhatday, simonK, Sithdown, skite2001, Smelly-Ghost, Stitch, Super Maker, t5b6_de, Tauwasser, TheNFCookie, Timville, twitnic, velipso, Veund, voltagex, Voultar, Warez Waldo, wickawack, Winter1760, Wkr, x7l7j8cc, xactoes, xukkorz, yosoo, Zeii, Zelante, zipplet, Zoo, zvxr
374
+ 2358, 90sFlav, AcoVanConis, AdmirtheSableye, AlexiG, ALXCO-Hardware, AndehX, antPL, aronson, Ausar, bbsan, BennVenn, ccs21, chobby, ClassicOldSong, Cliffback, 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, gandalf1980, gboh, gekkio, Godan, Grender, HDR, Herax, Hiccup, hiks, howie0210, iamevn, Icesythe7, ide, inYourBackline, iyatemu, Jayro, Jenetrix, JFox, joyrider3774, jrharbort, JS7457, julgr, Kaede, kane159, KOOORAY, kscheel, kyokohunter, Leitplanke, litlemoran, LovelyA72, Lu, Luca DS, LucentW, manuelcm1, marv17, Merkin, metroid-maniac, Mr_V, olDirdey, orangeglo, paarongiroux, Paradoxical, Rairch, Raphaël BOICHOT, redalchemy, RetroGorek, RevZ, RibShark, s1cp, Satumox, Sgt.DoudouMiel, SH, Shinichi999, Sillyhatday, simonK, Sithdown, skite2001, Smelly-Ghost, Sonikks, Squiddy, Stitch, Super Maker, t5b6_de, Tauwasser, TheNFCookie, Timville, twitnic, velipso, Veund, voltagex, Voultar, Warez Waldo, wickawack, Winter1760, Wkr, x7l7j8cc, xactoes, xukkorz, yosoo, Zeii, Zelante, zipplet, Zoo, zvxr
374
375
 
375
376
  ## Third Party Notices and Licenses
376
377
 
@@ -118,7 +118,7 @@ Use this command in a Terminal or Command Prompt window to launch the installed
118
118
  - DIY cart with MX29F040
119
119
  - DIY cart with MX29LV640
120
120
  - DIY cart with SST39SF040
121
- - DMG-MBC5-32M-FLASH Development Cartridge, E201264
121
+ - DMG-MBC5-32M-FLASH (G/A) Development Cartridge, E201264
122
122
  - Ferrante Crafts cart 32 KB
123
123
  - Ferrante Crafts cart 64 KB
124
124
  - Ferrante Crafts cart 512 KB
@@ -146,8 +146,9 @@ Use this command in a Terminal or Command Prompt window to launch the installed
146
146
  - Game Boy Advance
147
147
 
148
148
  - Action Replay Ultimate Codes (with SST39VF800A)
149
- - Development AGB Cartridge 64M Flash, E201629
150
- - Development AGB Cartridge 64M Flash S, E201843
149
+ - Development AGB Cartridge 64M Flash, E201629¹
150
+ - Development AGB Cartridge 64M Flash, E201629 (128M, with 4× LH28F320BJE)¹
151
+ - Development AGB Cartridge 64M Flash S, E201843¹
151
152
  - Development AGB Cartridge 128M Flash S, E201850
152
153
  - Development AGB Cartridge 256M Flash S, E201868
153
154
  - DL9SEC GBA flashcart with TE28F128
@@ -297,7 +298,7 @@ Use this command in a Terminal or Command Prompt window to launch the installed
297
298
  - GA-07 with unlabeled flash chip
298
299
  - GE28F128W30 with 128W30B0
299
300
  - K5L2BX_32D_16D_V2 with K5L2833ATA
300
- - M36XXX_32A_EARTH with M36L0R8060B
301
+ - M36XXX_32A_EARTH with M36L0R806
301
302
  - M36XXX_T32_32D_16D with M36L0R806
302
303
  - M5M29-39VF512 with M5M29HD528
303
304
  - M5M29G130AN (no PCB text)
@@ -341,7 +342,7 @@ Many different reproduction cartridges share their flash chip command set, so ev
341
342
 
342
343
  The author would like to thank the following very kind people for their help, contributions or documentation (in alphabetical order):
343
344
 
344
- 2358, 90sFlav, AcoVanConis, AdmirtheSableye, AlexiG, ALXCO-Hardware, AndehX, antPL, aronson, Ausar, bbsan, BennVenn, ccs21, chobby, ClassicOldSong, Cliffback, 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, gandalf1980, 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, Lu, Luca DS, LucentW, manuelcm1, marv17, Merkin, metroid-maniac, Mr_V, olDirdey, orangeglo, paarongiroux, Paradoxical, Rairch, Raphaël BOICHOT, redalchemy, RetroGorek, RevZ, RibShark, s1cp, Satumox, Sgt.DoudouMiel, SH, Shinichi999, Sillyhatday, simonK, Sithdown, skite2001, Smelly-Ghost, Stitch, Super Maker, t5b6_de, Tauwasser, TheNFCookie, Timville, twitnic, velipso, Veund, voltagex, Voultar, Warez Waldo, wickawack, Winter1760, Wkr, x7l7j8cc, xactoes, xukkorz, yosoo, Zeii, Zelante, zipplet, Zoo, zvxr
345
+ 2358, 90sFlav, AcoVanConis, AdmirtheSableye, AlexiG, ALXCO-Hardware, AndehX, antPL, aronson, Ausar, bbsan, BennVenn, ccs21, chobby, ClassicOldSong, Cliffback, 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, gandalf1980, gboh, gekkio, Godan, Grender, HDR, Herax, Hiccup, hiks, howie0210, iamevn, Icesythe7, ide, inYourBackline, iyatemu, Jayro, Jenetrix, JFox, joyrider3774, jrharbort, JS7457, julgr, Kaede, kane159, KOOORAY, kscheel, kyokohunter, Leitplanke, litlemoran, LovelyA72, Lu, Luca DS, LucentW, manuelcm1, marv17, Merkin, metroid-maniac, Mr_V, olDirdey, orangeglo, paarongiroux, Paradoxical, Rairch, Raphaël BOICHOT, redalchemy, RetroGorek, RevZ, RibShark, s1cp, Satumox, Sgt.DoudouMiel, SH, Shinichi999, Sillyhatday, simonK, Sithdown, skite2001, Smelly-Ghost, Sonikks, Squiddy, Stitch, Super Maker, t5b6_de, Tauwasser, TheNFCookie, Timville, twitnic, velipso, Veund, voltagex, Voultar, Warez Waldo, wickawack, Winter1760, Wkr, x7l7j8cc, xactoes, xukkorz, yosoo, Zeii, Zelante, zipplet, Zoo, zvxr
345
346
 
346
347
  ## Third Party Notices and Licenses
347
348
 
@@ -8,7 +8,7 @@ with open("README.md", "r", encoding="utf-8") as fh: long_description = fh.read(
8
8
 
9
9
  setuptools.setup(
10
10
  name="FlashGBX",
11
- version="4.0.1",
11
+ version="4.2",
12
12
  author="Lesserkuma",
13
13
  description="Reads and writes Game Boy and Game Boy Advance cartridge data",
14
14
  url="https://github.com/lesserkuma/FlashGBX",
Binary file
Binary file
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes
File without changes