mirror of
https://github.com/lesserkuma/FlashGBX.git
synced 2026-03-21 17:44:30 -05:00
4.5
This commit is contained in:
parent
37ca12a4f1
commit
c694ca8b1e
BIN
.github/build/Ubuntu/builddata.tar.gz
vendored
BIN
.github/build/Ubuntu/builddata.tar.gz
vendored
Binary file not shown.
BIN
.github/build/Windows/PySide2/Python_3.8.10.7z
vendored
BIN
.github/build/Windows/PySide2/Python_3.8.10.7z
vendored
Binary file not shown.
82
.github/build/Windows/PySide2/setup.iss
vendored
82
.github/build/Windows/PySide2/setup.iss
vendored
|
|
@ -1,82 +0,0 @@
|
|||
; Script generated by the Inno Setup Script Wizard.
|
||||
; SEE THE DOCUMENTATION FOR DETAILS ON CREATING INNO SETUP SCRIPT FILES!
|
||||
|
||||
#define MyAppName "FlashGBX"
|
||||
#define MyAppVersion "<APP_VERSION>"
|
||||
#define MyAppPublisher "Lesserkuma"
|
||||
#define MyAppURL "https://github.com/lesserkuma/FlashGBX"
|
||||
#define MyAppExeName "FlashGBX-app.exe"
|
||||
#define MyFilesDir "<FILES_DIR>"
|
||||
#define MyCH341Dir "<CH341_DIR>"
|
||||
#define MyOutputDir "<OUTPUT_DIR>"
|
||||
|
||||
[Setup]
|
||||
; NOTE: The value of AppId uniquely identifies this application. Do not use the same AppId value in installers for other applications.
|
||||
; (To generate a new GUID, click Tools | Generate GUID inside the IDE.)
|
||||
AppId={{060FD4CF-E72F-497D-812E-EB5599D59A0A}
|
||||
AppName={#MyAppName}
|
||||
AppVersion={#MyAppVersion}
|
||||
AppVerName={#MyAppName} v{#MyAppVersion}
|
||||
AppPublisher={#MyAppPublisher}
|
||||
AppPublisherURL={#MyAppURL}
|
||||
AppSupportURL={#MyAppURL}
|
||||
AppUpdatesURL={#MyAppURL}
|
||||
DefaultDirName={autopf}\{#MyAppName}
|
||||
DisableProgramGroupPage=yes
|
||||
;PrivilegesRequiredOverridesAllowed=dialog
|
||||
OutputDir={#MyOutputDir}
|
||||
OutputBaseFilename=Setup_FlashGBX
|
||||
Compression=lzma2/ultra64
|
||||
SolidCompression=yes
|
||||
WizardStyle=modern
|
||||
UninstallDisplayIcon={app}\FlashGBX-app.exe
|
||||
UninstallDisplayName={#MyAppName} v{#MyAppVersion}
|
||||
PrivilegesRequired=lowest
|
||||
ArchitecturesAllowed=x64compatible
|
||||
ArchitecturesInstallIn64BitMode=x64compatible
|
||||
|
||||
[Languages]
|
||||
Name: "english"; MessagesFile: "compiler:Default.isl"
|
||||
|
||||
[Types]
|
||||
Name: "full"; Description: "Install Application and Drivers"
|
||||
Name: "custom"; Description: "Custom Installation"; Flags: iscustom
|
||||
|
||||
[Components]
|
||||
Name: "program"; Description: "FlashGBX application"; Types: full custom; Flags: fixed
|
||||
Name: "driver_ch341"; Description: "CH340/CH341 driver v3.8.2023.02 for GBxCart RW and GBFlash (install/re-install)"; Types: full
|
||||
|
||||
[Tasks]
|
||||
Name: "desktopicon"; Description: "{cm:CreateDesktopIcon}"; GroupDescription: "{cm:AdditionalIcons}"
|
||||
|
||||
[Files]
|
||||
Source: "{#MyFilesDir}\*"; DestDir: "{app}"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: program
|
||||
Source: "{#MyCH341Dir}\*.*"; DestDir: "{app}\Drivers\CH341"; Flags: ignoreversion recursesubdirs createallsubdirs; Components: driver_ch341
|
||||
; NOTE: Don't use "Flags: ignoreversion" on any shared system files
|
||||
|
||||
[Icons]
|
||||
Name: "{autoprograms}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}";
|
||||
Name: "{autodesktop}\{#MyAppName}"; Filename: "{app}\{#MyAppExeName}"; Tasks: desktopicon
|
||||
|
||||
[Run]
|
||||
Filename: "{app}\Drivers\CH341\CH341SER.EXE"; Description: "Install CH340/CH341 driver"; Flags: waituntilterminated; Components: driver_ch341
|
||||
Filename: "{app}\Python_3.8.10\python.exe"; Parameters: "-m pip install PySide2==5.15.2.1 --no-warn-script-location --isolated --cache-dir {app}\Python_3.8.10\cache"; StatusMsg: "Setting up prerequisites in embedded Python runtime (only used for FlashGBX)..."; Flags: waituntilterminated runminimized; Components: program
|
||||
Filename: "{app}\{#MyAppExeName}"; Description: "{cm:LaunchProgram,{#StringChange(MyAppName, '&', '&&')}}"; Flags: nowait postinstall skipifsilent
|
||||
|
||||
[InstallDelete]
|
||||
Type: filesandordirs; Name: "{app}\Python";
|
||||
Type: filesandordirs; Name: "{app}\Python_3.8.10";
|
||||
Type: filesandordirs; Name: "{app}\*.pyd";
|
||||
|
||||
[Code]
|
||||
procedure CurUninstallStepChanged(CurUninstallStep: TUninstallStep);
|
||||
begin
|
||||
if CurUninstallStep = usPostUninstall then
|
||||
begin
|
||||
DelTree(ExpandConstant('{app}'), True, True, True);
|
||||
if MsgBox('Delete all config files of FlashGBX as well?', mbConfirmation, MB_YESNO or MB_DEFBUTTON2) = IDYES then
|
||||
begin
|
||||
DelTree(ExpandConstant('{localappdata}\{#MyAppName}'), True, True, True);
|
||||
end;
|
||||
end;
|
||||
end;
|
||||
BIN
.github/build/Windows/PySide6/Python_3.10.11.7z
vendored
BIN
.github/build/Windows/PySide6/Python_3.10.11.7z
vendored
Binary file not shown.
2
.github/workflows/build-macos.yaml
vendored
2
.github/workflows/build-macos.yaml
vendored
|
|
@ -49,7 +49,7 @@ jobs:
|
|||
run: |
|
||||
python -m venv ${{ github.workspace }}/venv
|
||||
source ${{ github.workspace }}/venv/bin/activate
|
||||
python -m pip install pyinstaller==6.11.0 Pillow==10.3.0 PySide6==6.7.2 pyserial==3.5 python-dateutil==2.9.0.post0 requests==2.32.3
|
||||
python -m pip install pyinstaller==6.11.0 Pillow==10.3.0 PySide6==6.7.2 pyserial==3.5 python-dateutil==2.9.0.post0 requests==2.32.3 packaging==25.0
|
||||
|
||||
- name: Build FlashGBX
|
||||
run: |
|
||||
|
|
|
|||
10
CHANGES.md
10
CHANGES.md
|
|
@ -1,4 +1,12 @@
|
|||
# Release notes
|
||||
### v4.5 (released 2025-12-06)
|
||||
- Added support for SD007_T40_6401B\*CD_71_TS28 with 39VF6401B
|
||||
- Added support for ModRetro Chromatic Cartridge with IS29GL032 *(thanks Jayro)*
|
||||
- Added support for MXP54_16D_ERATH with MSP54LV256
|
||||
- Added support for a new Game Boy Advance bootleg flash save chip
|
||||
- Confirmed support for MXP54_16D_046 with MSP54LV256
|
||||
- Updated the Game Boy and Game Boy Advance lookup databases for save types, ROM sizes and checksums
|
||||
|
||||
### v4.4 (released 2025-05-23)
|
||||
- Added a few workarounds for instabilities with some GBxCart RW devices
|
||||
- Fixed save data access for “Korokoro Puzzle - Happy Panecchu!” (AGB-KHPJ-JPN)
|
||||
|
|
@ -423,7 +431,7 @@
|
|||
- Confirmed support for SD007_TSOP_48BALL_V10 with GL032M10BFIR3 *(thanks Mr_V)*
|
||||
- Added support for 2006_TSOP_64BALL_6106 with W29GL128SH9B *(thanks marv17)*
|
||||
- Fixed support for insideGadgets 1 MB, 128 KB SRAM *(thanks AlexiG)*
|
||||
- The [setup package](https://github.com/lesserkuma/FlashGBX/releases) now includes the CH341 USB serial driver for insideGadgets GBxCart RW devices
|
||||
- The [setup package](https://github.com/Lesserkuma/FlashGBX/releases) now includes the CH341 USB serial driver for insideGadgets GBxCart RW devices
|
||||
|
||||
### v2.2 (released 2021-06-03)
|
||||
- Added support for insideGadgets 2 MB, 32 KB FRAM, v1.0 *(thanks t5b6_de)*
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
import traceback
|
||||
from serial import SerialException
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
import sys, os, glob, re, json, zlib, argparse, zipfile, traceback, platform, datetime, copy
|
||||
from . import Util
|
||||
|
|
@ -88,7 +88,7 @@ def main(portableMode=False):
|
|||
os.environ['QT_MAC_WANTS_LAYER'] = '1'
|
||||
|
||||
print("{:s} {:s} by Lesserkuma".format(Util.APPNAME, Util.VERSION))
|
||||
print("https://github.com/lesserkuma/FlashGBX")
|
||||
print("https://github.com/Lesserkuma/FlashGBX")
|
||||
|
||||
if getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS'):
|
||||
app_path = os.path.dirname(sys.executable)
|
||||
|
|
@ -139,6 +139,7 @@ def main(portableMode=False):
|
|||
ap_cli2.add_argument("--agb-romsize", choices=["auto", "32kb", "64kb", "128kb", "256kb", "512kb", "1mb", "2mb", "4mb", "8mb", "16mb", "32mb", "64mb", "128mb", "256mb", "512mb"], type=str.lower, default="auto", help="set size of Game Boy Advance cartridge ROM data")
|
||||
ap_cli2.add_argument("--agb-savetype", choices=["auto", "eeprom4k", "eeprom64k", "sram256k", "flash512k", "flash1m", "dacs8m", "sram512k", "sram1m"], type=str.lower, default="auto", help="set type of Game Boy Advance cartridge save data")
|
||||
ap_cli2.add_argument("--store-rtc", action="store_true", default=False, help="store RTC register values if supported")
|
||||
ap_cli2.add_argument("--keep-calibration", action="store_true", default=True, help="keep existing calibration data of the e-Reader when writing save data")
|
||||
ap_cli2.add_argument("--ignore-bad-header", action="store_true", help="don’t stop if invalid data found in cartridge header data")
|
||||
ap_cli2.add_argument("--flashcart-type", type=str, default="autodetect", help="name of flash cart; see txt files in config directory")
|
||||
ap_cli2.add_argument("--prefer-chip-erase", action="store_true", help="prefer full chip erase over sector erase when both available")
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
import datetime, shutil, platform, os, math, traceback, re, time, serial, zipfile
|
||||
try:
|
||||
|
|
@ -485,6 +485,9 @@ class FlashGBX_CLI():
|
|||
bad_read = False
|
||||
s = ""
|
||||
if self.CONN.GetMode() == "DMG":
|
||||
if data["db"]:
|
||||
s += "Game Name: {:s}\n".format(os.path.splitext(Util.GenerateFileName(mode=self.CONN.GetMode(), header=self.CONN.INFO, settings=None))[0])
|
||||
|
||||
s += "Game Title: {:s}\n".format(data["game_title"])
|
||||
if len(data['game_code']) > 0:
|
||||
s += "Game Code: {:s}\n".format(data['game_code'])
|
||||
|
|
@ -554,6 +557,9 @@ class FlashGBX_CLI():
|
|||
self.ARGS["argparsed"].flashcart_type = cart_types[0][i]
|
||||
|
||||
elif self.CONN.GetMode() == "AGB":
|
||||
if data["db"]:
|
||||
s += "Game Name: {:s}\n".format(os.path.splitext(Util.GenerateFileName(mode=self.CONN.GetMode(), header=self.CONN.INFO, settings=None))[0])
|
||||
|
||||
s += "Game Title: {:s}\n".format(data["game_title"])
|
||||
s += "Game Code: {:s}\n".format(data["game_code"])
|
||||
s += "Revision: {:d}\n".format(data["version"])
|
||||
|
|
@ -1160,7 +1166,7 @@ class FlashGBX_CLI():
|
|||
if "ereader_calibration" in self.CONN.INFO:
|
||||
with open(path, "rb") as f: buffer = bytearray(f.read())
|
||||
if buffer[0xD000:0xF000] != self.CONN.INFO["ereader_calibration"]:
|
||||
if not args.overwrite:
|
||||
if args.keep_calibration:
|
||||
if args.action == "erase-save": args.action = "restore-save"
|
||||
print("Note: Keeping existing e-Reader calibration data.")
|
||||
buffer[0xD000:0xF000] = self.CONN.INFO["ereader_calibration"]
|
||||
|
|
|
|||
|
|
@ -1,12 +1,13 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
import sys, os, time, datetime, json, platform, subprocess, requests, webbrowser, pkg_resources, threading, calendar, queue
|
||||
import sys, os, time, datetime, json, platform, subprocess, requests, webbrowser, threading, calendar, queue
|
||||
from .pyside import QtCore, QtWidgets, QtGui, QApplication
|
||||
from PIL.ImageQt import ImageQt
|
||||
from PIL import Image
|
||||
from serial import SerialException
|
||||
from packaging import version
|
||||
from .RomFileDMG import RomFileDMG
|
||||
from .RomFileAGB import RomFileAGB
|
||||
from .PocketCameraWindow import PocketCameraWindow
|
||||
|
|
@ -204,7 +205,7 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
self.mnuConfig.addAction("Use &No-Intro file names", lambda: self.SETTINGS.setValue("UseNoIntroFilenames", str(self.mnuConfig.actions()[7].isChecked()).lower().replace("true", "enabled").replace("false", "disabled")))
|
||||
self.mnuConfig.addAction("Automatic cartridge &power off", lambda: [ self.SETTINGS.setValue("AutoPowerOff", str(self.mnuConfig.actions()[8].isChecked()).lower().replace("true", "350").replace("false", "0")), self.SetAutoPowerOff() ])
|
||||
self.mnuConfig.addAction("Skip writing matching ROM chunk&s", lambda: self.SETTINGS.setValue("CompareSectors", str(self.mnuConfig.actions()[9].isChecked()).lower().replace("true", "enabled").replace("false", "disabled")))
|
||||
self.mnuConfig.addAction("Alternative address set mode (can fix or cause write errors)", lambda: self.SETTINGS.setValue("ForceWrPullup", str(self.mnuConfig.actions()[10].isChecked()).lower().replace("true", "enabled").replace("false", "disabled")))
|
||||
self.mnuConfig.addAction("Alternate address set mode (can fix or cause write errors)", lambda: self.SETTINGS.setValue("ForceWrPullup", str(self.mnuConfig.actions()[10].isChecked()).lower().replace("true", "enabled").replace("false", "disabled")))
|
||||
self.mnuConfig.addSeparator()
|
||||
self.mnuConfigReadModeAGB = QtWidgets.QMenu("&Read Method (Game Boy Advance)")
|
||||
self.mnuConfigReadModeAGB.addAction("S&tream", lambda: [ self.SETTINGS.setValue("AGBReadMethod", str(self.mnuConfigReadModeAGB.actions()[1].isChecked()).lower().replace("true", "2")), self.SetAGBReadMethod() ])
|
||||
|
|
@ -629,8 +630,8 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
self.SETTINGS.setValue("UpdateCheck", "disabled")
|
||||
if update_check and update_check.lower() == "enabled":
|
||||
print("")
|
||||
url = "https://api.github.com/repos/lesserkuma/FlashGBX/releases/latest"
|
||||
site = "https://github.com/lesserkuma/FlashGBX/releases/latest"
|
||||
url = "https://api.github.com/repos/Lesserkuma/FlashGBX/releases/latest"
|
||||
site = "https://github.com/Lesserkuma/FlashGBX/releases/latest"
|
||||
try:
|
||||
ret = requests.get(url, allow_redirects=True, timeout=1.5)
|
||||
except requests.exceptions.ConnectTimeout as e:
|
||||
|
|
@ -648,9 +649,9 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
ret = json.loads(ret)
|
||||
if 'tag_name' in ret:
|
||||
latest_version = str(ret['tag_name'])
|
||||
if pkg_resources.parse_version(latest_version) == pkg_resources.parse_version(VERSION_PEP440):
|
||||
if version.parse(latest_version) == version.parse(VERSION_PEP440):
|
||||
print("You are using the latest version of {:s}.".format(APPNAME))
|
||||
elif pkg_resources.parse_version(latest_version) > pkg_resources.parse_version(VERSION_PEP440):
|
||||
elif version.parse(latest_version) > version.parse(VERSION_PEP440):
|
||||
msg_text = "A new version of {:s} has been released!\nVersion {:s} is now available.".format(APPNAME, latest_version)
|
||||
print(msg_text)
|
||||
msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Question, windowTitle="{:s} Update Check".format(APPNAME), text=msg_text)
|
||||
|
|
@ -725,14 +726,14 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
def AboutFlashGBX(self):
|
||||
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>"
|
||||
msg += f"© 2020–{datetime.datetime.now().year} Lesserkuma<br>"
|
||||
msg += "• Website: <a href=\"https://github.com/lesserkuma/FlashGBX\">https://github.com/lesserkuma/FlashGBX</a><br><br>"
|
||||
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, delibird_deals, DevDavisNunez, Diddy_Kong, djedditt, Dr-InSide, dyf2007, easthighNerd, EchelonPrime, edo999, Eldram, Ell, EmperorOfTigers, endrift, Erba Verde, ethanstrax, eveningmoose, Falknör, FerrantePescara, frarees, Frost Clock, Gahr, gandalf1980, gboh, gekkio, Godan, Grender, HDR, Herax, Hiccup, hiks, howie0210, iamevn, Icesythe7, ide, infinest, inYourBackline, iyatemu, Jayro, Jenetrix, JFox, joyrider3774, jrharbort, JS7457, julgr, Kaede, kane159, KOOORAY, kscheel, kyokohunter, Leitplanke, litlemoran, LovelyA72, Lu, Luca DS, LucentW, luxkiller65, manuelcm1, marv17, Merkin, metroid-maniac, Mr_V, Mufsta, 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"
|
||||
msg += "• Website: <a href=\"https://github.com/Lesserkuma/FlashGBX\">https://github.com/Lesserkuma/FlashGBX</a><br><br>"
|
||||
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, delibird_deals, DevDavisNunez, Diddy_Kong, djedditt, Dr-InSide, dyf2007, easthighNerd, EchelonPrime, edo999, Eldram, Ell, EmperorOfTigers, endrift, Erba Verde, ethanstrax, eveningmoose, Falknör, FerrantePescara, frarees, Frost Clock, Gahr, gandalf1980, gboh, gekkio, Godan, Grender, HDR, Herax, Hiccup, hiks, howie0210, iamevn, Icesythe7, ide, infinest, inYourBackline, iyatemu, Jayro, Jenetrix, JFox, joyrider3774, jrharbort, JS7457, julgr, Kaede, kane159, KOOORAY, kscheel, kyokohunter, Leif, Leitplanke, litlemoran, LovelyA72, Lu, Luca DS, LucentW, luxkiller65, manuelcm1, marv17, Merkin, metroid-maniac, Mr_V, Mufsta, 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"
|
||||
QtWidgets.QMessageBox.information(self, "{:s} {:s}".format(APPNAME, VERSION), msg, QtWidgets.QMessageBox.Ok)
|
||||
|
||||
def AboutGameDB(self):
|
||||
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>"
|
||||
msg += f"No-Intro databases referenced for this version of {APPNAME}:<br>"
|
||||
msg += "• Nintendo - Game Boy (20250427-010043)<br>• Nintendo - Game Boy Advance (20250516-204815)<br>• Nintendo - Game Boy Advance (Video) (20241213-211743)<br>• Nintendo - Game Boy Color (20250516-032234)" # No-Intro DBs
|
||||
msg += "• Nintendo - Game Boy (20251203-165423)<br>• Nintendo - Game Boy Advance (20251202-225320)<br>• Nintendo - Game Boy Advance (Video) (20251114-101831)<br>• Nintendo - Game Boy Color (20251127-150925)" # No-Intro DBs
|
||||
QtWidgets.QMessageBox.information(self, "{:s} {:s}".format(APPNAME, VERSION), msg, QtWidgets.QMessageBox.Ok)
|
||||
|
||||
def OpenPath(self, path=None):
|
||||
|
|
@ -887,7 +888,7 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
text = "A firmware update for your {:s} device is required to use this software. Do you want to update now?".format(dev.GetFullName())
|
||||
msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Warning, windowTitle="{:s} {:s}".format(APPNAME, VERSION), text=text, standardButtons=QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, defaultButton=QtWidgets.QMessageBox.Yes)
|
||||
elif dev.FW_UPDATE_REQ == 2:
|
||||
text = "Your {:s} device is no longer supported in this version of FlashGBX due to technical limitations. The last supported version is <a href=\"https://github.com/lesserkuma/FlashGBX/releases/tag/3.37\">FlashGBX v3.37</a>.\n\nYou can still use the Firmware Updater, however any other functions are no longer available.\n\nDo you want to run the Firmware Updater now?".format(dev.GetFullName()).replace("\n", "<br>")
|
||||
text = "Your {:s} device is no longer supported in this version of FlashGBX due to technical limitations. The last supported version is <a href=\"https://github.com/Lesserkuma/FlashGBX/releases/tag/3.37\">FlashGBX v3.37</a>.\n\nYou can still use the Firmware Updater, however any other functions are no longer available.\n\nDo you want to run the Firmware Updater now?".format(dev.GetFullName()).replace("\n", "<br>")
|
||||
msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Warning, windowTitle="{:s} {:s}".format(APPNAME, VERSION), text=text, standardButtons=QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No, defaultButton=QtWidgets.QMessageBox.Yes)
|
||||
else:
|
||||
text = "A firmware update for your {:s} device is available. Do you want to update now?".format(dev.GetFullName())
|
||||
|
|
@ -988,7 +989,7 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
"- Check if the operating system detects the device (if not, reboot your machine)\n" \
|
||||
"- Update the firmware through Options → Tools → Firmware Updater"
|
||||
if platform.system() == "Darwin":
|
||||
msg += "\n - <b>For Joey Jr on macOS:</b> Use the dedicated <a href=\"https://github.com/lesserkuma/JoeyJr_FWUpdater\">Firmware Updater for Joey Jr</a>"
|
||||
msg += "\n - <b>For Joey Jr on macOS:</b> Use the dedicated <a href=\"https://github.com/Lesserkuma/JoeyJr_FWUpdater\">Firmware Updater for Joey Jr</a>"
|
||||
elif platform.system() == "Linux":
|
||||
msg += "\n- <b>For Linux users:</b> Ensure your user account has permissions to use the device (try adding yourself to user groups “dialout” or “uucp”)"
|
||||
|
||||
|
|
@ -2273,11 +2274,11 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
detected = False
|
||||
if detected is False:
|
||||
intro_msg = "In order to access Batteryless SRAM save data, its ROM location and size must be specified.\n\n"
|
||||
if mode == "AGB":
|
||||
max_size = self.cmbAGBHeaderROMSizeResult.currentText().replace(" ", " ")
|
||||
elif mode == "DMG":
|
||||
max_size = self.cmbDMGHeaderROMSizeResult.currentText().replace(" ", " ")
|
||||
intro_msg2 = "⚠️ The required parameters could not be auto-detected. Please enter the ROM location and size manually below. Note that wrong values can corrupt your game upon writing, so having a full " + max_size + " ROM backup is recommended."
|
||||
# if mode == "AGB":
|
||||
# max_size = self.cmbAGBHeaderROMSizeResult.currentText().replace(" ", " ")
|
||||
# elif mode == "DMG":
|
||||
# max_size = self.cmbDMGHeaderROMSizeResult.currentText().replace(" ", " ")
|
||||
intro_msg2 = "⚠️ The required parameters could not be auto-detected. Please enter the ROM location and size manually below. Note that wrong values can corrupt your game upon writing, so having a full ROM backup is recommended."
|
||||
|
||||
if mode == "DMG":
|
||||
# Load database of observed configurations from various bootlegs
|
||||
|
|
@ -2600,7 +2601,7 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
self.CONN.SetMode("DMG")
|
||||
elif self.optAGB.isChecked() and (mode == "DMG" or mode == None):
|
||||
self.CONN.SetMode("AGB")
|
||||
except BrokenPipeError:
|
||||
except (BrokenPipeError, SerialException):
|
||||
msg = "Failed to turn on the cartridge power.\n\nThe “Automatic cartridge power off” setting has therefore been disabled. Please re-connect the device and try again."
|
||||
self.mnuConfig.actions()[5].setChecked(False)
|
||||
self.SETTINGS.setValue("AutoPowerOff", "0")
|
||||
|
|
@ -2635,7 +2636,7 @@ class FlashGBX_GUI(QtWidgets.QWidget):
|
|||
|
||||
try:
|
||||
data = self.CONN.ReadInfo(setPinsAsInputs=True)
|
||||
except SerialException:
|
||||
except (BrokenPipeError, SerialException):
|
||||
self.LimitBaudRateGBxCartRW()
|
||||
self.DisconnectDevice()
|
||||
QtWidgets.QMessageBox.critical(self, "{:s} {:s}".format(APPNAME, VERSION), "The connection to the device was lost while trying to read the ROM header. This may happen if the inserted cartridge issues a short circuit or its peak power draw is too high.\n\nAs a potential workaround for the latter, you can try hotswapping the cartridge:\n1. Remove the cartridge from the device.\n2. Reconnect the device and select mode.\n3. Then insert the cartridge and click “{:s}”.".format(self.btnHeaderRefresh.text().replace("&", "")), QtWidgets.QMessageBox.Ok)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
import time, copy, math, struct
|
||||
from .Util import dprint, bitswap
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
import datetime, struct, copy, zlib, hashlib
|
||||
from . import Util
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
import time, math, struct, traceback, zlib, copy, hashlib, os, datetime, platform, json, base64
|
||||
import serial, serial.tools.list_ports
|
||||
|
|
@ -147,6 +147,7 @@ class LK_Device(ABC):
|
|||
AGB_READ_METHODS = ["Single", "MemCpy", "Stream"]
|
||||
LAST_CHECK_ACTIVE = 0
|
||||
USER_ANSWER = None
|
||||
SKIP_POWERCYCLE = False
|
||||
|
||||
def __init__(self):
|
||||
pass
|
||||
|
|
@ -721,7 +722,7 @@ class LK_Device(ABC):
|
|||
continue
|
||||
|
||||
def CartPowerCycle(self, delay=0.1):
|
||||
if self.CanPowerCycleCart():
|
||||
if self.CanPowerCycleCart() and not self.SKIP_POWERCYCLE:
|
||||
dprint("Power cycling cartridge with a delay of {:.1f} seconds".format(delay))
|
||||
self.CartPowerOff(delay=delay)
|
||||
self.CartPowerOn(delay=delay)
|
||||
|
|
@ -868,6 +869,7 @@ class LK_Device(ABC):
|
|||
dprint(f"Setting automatic power off time value to {value}")
|
||||
self._set_fw_variable("AUTO_POWEROFF_TIME", value)
|
||||
self._set_fw_variable("AUTO_POWEROFF_ENABLED", 1 if value != 0 else 0)
|
||||
self.SKIP_POWERCYCLE = False if value != 0 else True
|
||||
|
||||
def GetSupportedCartridgesDMG(self):
|
||||
return (list(self.SUPPORTED_CARTS['DMG'].keys()), list(self.SUPPORTED_CARTS['DMG'].values()))
|
||||
|
|
@ -1104,7 +1106,7 @@ class LK_Device(ABC):
|
|||
if self.MODE == "DMG": #and setPinsAsInputs:
|
||||
self._write(self.DEVICE_CMD["SET_ADDR_AS_INPUTS"], wait=self.FW["fw_ver"] >= 12)
|
||||
|
||||
self.Debug()
|
||||
#self.Debug()
|
||||
return data
|
||||
|
||||
def _DetectCartridge(self, args): # Wrapper for thread call
|
||||
|
|
@ -1140,7 +1142,7 @@ class LK_Device(ABC):
|
|||
|
||||
# Disable Auto Power Off
|
||||
_apoe = False
|
||||
if self.FW["fw_ver"] >= 12:
|
||||
if self.FW["fw_ver"] >= 12 and self.SKIP_POWERCYCLE is False:
|
||||
if self.CanPowerCycleCart():
|
||||
self.CartPowerCycle()
|
||||
_apoe = self._get_fw_variable("AUTO_POWEROFF_ENABLED") == 1
|
||||
|
|
@ -1266,7 +1268,7 @@ class LK_Device(ABC):
|
|||
save_size = Util.AGB_Flash_Save_Chips_Sizes[list(Util.AGB_Flash_Save_Chips).index(flash_save_id)]
|
||||
save_chip = Util.AGB_Flash_Save_Chips[flash_save_id]
|
||||
|
||||
if flash_save_id in (0xBF5B, 0xFFFF): # Bootlegs
|
||||
if flash_save_id in (0xBF4B, 0xBF5B, 0xFFFF): # Bootlegs
|
||||
if self.INFO["data"][0:0x20000] == bytearray([0xFF] * 0x20000):
|
||||
save_type = 5
|
||||
elif self.INFO["data"][0:0x10000] == self.INFO["data"][0x10000:0x20000]:
|
||||
|
|
@ -1332,7 +1334,7 @@ class LK_Device(ABC):
|
|||
self.INFO["last_action"] = 0
|
||||
self.INFO["action"] = None
|
||||
|
||||
if self.CanPowerCycleCart() and _apoe is True:
|
||||
if self.CanPowerCycleCart() and _apoe is True and self.SKIP_POWERCYCLE is False:
|
||||
self._set_fw_variable("AUTO_POWEROFF_TIME", _apot)
|
||||
|
||||
return (info, save_size, save_type, save_chip, sram_unstable, cart_types, cart_type_id, cfi_s, cfi, flash_id, detected_size)
|
||||
|
|
@ -2882,6 +2884,7 @@ class LK_Device(ABC):
|
|||
|
||||
# Calculate Global Checksum
|
||||
if self.MODE == "DMG":
|
||||
self.INFO["dump_info"]["header"].update(RomFileDMG(buffer[:0x180]).GetHeader(unchanged=True))
|
||||
if _mbc.GetName() == "MMM01":
|
||||
self.INFO["dump_info"]["header"].update(RomFileDMG(buffer[-0x8000:-0x8000+0x180]).GetHeader(unchanged=True))
|
||||
elif _mbc.GetName() == "Sachen":
|
||||
|
|
@ -3118,7 +3121,7 @@ class LK_Device(ABC):
|
|||
return False
|
||||
buffer_len = 0x1000
|
||||
(agb_flash_chip, _) = ret
|
||||
if agb_flash_chip in (0xBF5B, 0xFFFF): # Bootlegs
|
||||
if agb_flash_chip in (0xBF4B, 0xBF5B, 0xFFFF): # Bootlegs
|
||||
buffer_len = 0x800
|
||||
elif args["save_type"] == 6: # DACS
|
||||
# self._write(self.DEVICE_CMD["AGB_BOOTUP_SEQUENCE"], wait=self.FW["fw_ver"] >= 12)
|
||||
|
|
@ -3255,7 +3258,7 @@ class LK_Device(ABC):
|
|||
end_address = min(save_size, bank_size)
|
||||
|
||||
if save_size > bank_size:
|
||||
if args["save_type"] == 8 or agb_flash_chip in (0xBF5B, 0xFFFF): # Bootleg 1M
|
||||
if args["save_type"] == 8 or agb_flash_chip in (0xBF4B, 0xBF5B, 0xFFFF): # Bootleg 1M
|
||||
dprint("Switching to bootleg save bank {:d}".format(bank))
|
||||
self._cart_write(0x1000000, bank)
|
||||
elif args["save_type"] == 5: # FLASH 1M
|
||||
|
|
@ -3563,7 +3566,7 @@ class LK_Device(ABC):
|
|||
buffer[0xFF80:0x10000] = self.INFO["data"][0xFF80:0x10000]
|
||||
buffer[0x1FF80:0x20000] = self.INFO["data"][0xFF80:0x10000]
|
||||
|
||||
elif (self.INFO["data"][:end_address] != buffer[:end_address]):
|
||||
if (self.INFO["data"][:end_address] != buffer[:end_address]):
|
||||
msg = ""
|
||||
count = 0
|
||||
time_start = time.time()
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
import time, datetime, struct, math, hashlib
|
||||
from dateutil.relativedelta import relativedelta
|
||||
|
|
@ -260,13 +260,6 @@ class DMG_MBC3(DMG_MBC):
|
|||
def GetName(self):
|
||||
return "MBC3"
|
||||
|
||||
def EnableRAM(self, enable=True):
|
||||
dprint(self.GetName(), "|", enable)
|
||||
commands = [
|
||||
[ 0x0000, 0x0A if enable else 0x00 ],
|
||||
]
|
||||
self.CartWrite(commands)
|
||||
|
||||
def HasRTC(self):
|
||||
dprint("Checking for RTC")
|
||||
if self.MBC_ID not in (0x0F, 0x10, 0x110, 0x206):
|
||||
|
|
@ -472,20 +465,6 @@ class DMG_MBC5(DMG_MBC):
|
|||
def GetName(self):
|
||||
return "MBC5"
|
||||
|
||||
def EnableRAM(self, enable=True):
|
||||
dprint(self.GetName(), "|", enable)
|
||||
if enable:
|
||||
commands = [
|
||||
[ 0x6000, 0x01 ],
|
||||
[ 0x0000, 0x0A ],
|
||||
]
|
||||
else:
|
||||
commands = [
|
||||
[ 0x0000, 0x00 ],
|
||||
[ 0x6000, 0x00 ],
|
||||
]
|
||||
self.CartWrite(commands)
|
||||
|
||||
def SelectBankROM(self, index):
|
||||
dprint(self.GetName(), "|", index)
|
||||
|
||||
|
|
@ -701,7 +680,7 @@ class DMG_MMM01(DMG_MBC):
|
|||
class DMG_GBD(DMG_MBC5):
|
||||
def GetName(self):
|
||||
return "MAC-GBD"
|
||||
|
||||
|
||||
def SelectBankROM(self, index):
|
||||
dprint(self.GetName(), "|", index)
|
||||
commands = [
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
from PIL import Image
|
||||
from PIL.PngImagePlugin import PngInfo
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
import functools, os, json, platform, shutil
|
||||
from PIL.ImageQt import ImageQt
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
import hashlib, re, zlib, string, os, json, copy, struct
|
||||
from . import Util
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
import hashlib, re, string, struct, os, json, copy
|
||||
from . import Util
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
from .pyside import QtCore, QtWidgets, QtGui
|
||||
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
import math, time, datetime, copy, configparser, threading, os, platform, traceback, io, struct, re, statistics, random, sys
|
||||
from io import StringIO
|
||||
|
|
@ -8,9 +8,9 @@ from enum import Enum
|
|||
|
||||
# Common constants
|
||||
APPNAME = "FlashGBX"
|
||||
VERSION_PEP440 = "4.4"
|
||||
VERSION_PEP440 = "4.5"
|
||||
VERSION = "v{:s}".format(VERSION_PEP440)
|
||||
VERSION_TIMESTAMP = 1748007939
|
||||
VERSION_TIMESTAMP = 1765034084
|
||||
DEBUG = False
|
||||
DEBUG_LOG = []
|
||||
APP_PATH = ""
|
||||
|
|
@ -20,8 +20,8 @@ AGB_Header_ROM_Sizes = [ "32 KiB", "64 KiB", "128 KiB", "256 KiB", "512 KiB", "1
|
|||
AGB_Header_ROM_Sizes_Map = [ 0x8000, 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000, 0x20000000 ]
|
||||
AGB_Header_Save_Types = [ "None", "4K EEPROM (512 Bytes)", "64K EEPROM (8 KiB)", "256K SRAM/FRAM (32 KiB)", "512K FLASH (64 KiB)", "1M FLASH (128 KiB)", "8M DACS (1 MiB)", "Unlicensed 512K SRAM (64 KiB)", "Unlicensed 1M SRAM (128 KiB)", "Unlicensed Batteryless SRAM" ]
|
||||
AGB_Header_Save_Sizes = [ 0, 512, 8192, 32768, 65536, 131072, 1048576, 65536, 131072, 0 ]
|
||||
AGB_Flash_Save_Chips = { 0xBFD4:"SST 39VF512", 0x1F3D:"Atmel AT29LV512", 0xC21C:"Macronix MX29L512", 0x321B:"Panasonic MN63F805MNP", 0xC209:"Macronix MX29L010", 0x6213:"SANYO LE26FV10N1TS", 0xBF5B:"Unlicensed SST49LF080A", 0xFFFF:"Unlicensed 0xFFFF" }
|
||||
AGB_Flash_Save_Chips_Sizes = [ 0x10000, 0x10000, 0x10000, 0x10000, 0x20000, 0x20000, 0x20000, 0x20000 ]
|
||||
AGB_Flash_Save_Chips = { 0xBFD4:"SST 39VF512", 0x1F3D:"Atmel AT29LV512", 0xC21C:"Macronix MX29L512", 0x321B:"Panasonic MN63F805MNP", 0xC209:"Macronix MX29L010", 0x6213:"SANYO LE26FV10N1TS", 0xBF4B:"Unlicensed SST25VF064C", 0xBF5B:"Unlicensed SST49LF080A", 0xFFFF:"Unlicensed 0xFFFF" }
|
||||
AGB_Flash_Save_Chips_Sizes = [ 0x10000, 0x10000, 0x10000, 0x10000, 0x20000, 0x20000, 0x20000, 0x20000, 0x20000 ]
|
||||
|
||||
DMG_Header_Mapper = { 0x00:'None', 0x01:'MBC1', 0x02:'MBC1+SRAM', 0x03:'MBC1+SRAM+BATTERY', 0x06:'MBC2+SRAM+BATTERY', 0x0F:'MBC3+RTC+BATTERY', 0x10:'MBC3+RTC+SRAM+BATTERY', 0x110:'MBC30+RTC+SRAM+BATTERY', 0x12:'MBC3+SRAM', 0x13:'MBC3+SRAM+BATTERY', 0x19:'MBC5', 0x1A:'MBC5+SRAM', 0x1B:'MBC5+SRAM+BATTERY', 0x1C:'MBC5+RUMBLE', 0x1E:'MBC5+RUMBLE+SRAM+BATTERY', 0x20:'MBC6+SRAM+FLASH+BATTERY', 0x22:'MBC7+ACCELEROMETER+EEPROM', 0x101:'MBC1M', 0x103:'MBC1M+SRAM+BATTERY', 0x0B:'MMM01', 0x0D:'MMM01+SRAM+BATTERY', 0xFC:'MAC-GBD+SRAM+BATTERY', 0x105:'G-MMC1+SRAM+BATTERY', 0x104:'M161', 0xFF:'HuC-1+IR+SRAM+BATTERY', 0xFE:'HuC-3+RTC+SRAM+BATTERY', 0xFD:'TAMA5+RTC+EEPROM', 0x201:'Unlicensed 256M Mapper', 0x202:'Unlicensed Wisdom Tree Mapper', 0x203:'Unlicensed Xploder GB Mapper', 0x204:'Unlicensed Sachen Mapper', 0x205:'Unlicensed Datel Orbit V2 Mapper', 0x206:'Unlicensed MBCX Mapper' }
|
||||
DMG_Mapper_Types = { "None":[ 0x00, 0x08, 0x09 ], "MBC1":[ 0x01, 0x02, 0x03 ], "MBC2":[ 0x05, 0x06 ], "MBC3":[ 0x0F, 0x10, 0x11, 0x12, 0x13 ], "MBC30":[ 0x110 ], "MBC5":[ 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E ], "MBC6":[ 0x20 ], "MBC7":[ 0x22 ], "MBC1M":[ 0x101, 0x103 ], "MMM01":[ 0x0B, 0x0D ], "MAC-GBD":[ 0xFC ], "G-MMC1":[ 0x105 ], "M161":[ 0x104 ], "HuC-1":[ 0xFF ], "HuC-3":[ 0xFE ], "TAMA5":[ 0xFD ], "Unlicensed 256M Multi Cart Mapper":[ 0x201 ], "Unlicensed Wisdom Tree Mapper":[ 0x202 ], "Unlicensed Xploder GB Mapper":[ 0x203 ], "Unlicensed Sachen Mapper":[ 0x204 ], "Unlicensed Datel Orbit V2 Mapper":[ 0x205 ], "Unlicensed MBCX Mapper":[ 0x206 ] }
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
from . import FlashGBX
|
||||
FlashGBX.main()
|
||||
|
|
|
|||
|
|
@ -3,11 +3,13 @@
|
|||
"names":[
|
||||
"BX2006_TSOP_64BALL with GL256S",
|
||||
"BGA64B-71-TV-DEEP with 256M29EML",
|
||||
"FunnyPlaying MidnightTrace 32 MiB Flash Cart"
|
||||
"FunnyPlaying MidnightTrace 32 MiB Flash Cart",
|
||||
"MXP54_16D_046 with MSP54LV256"
|
||||
],
|
||||
"flash_ids":[
|
||||
[ 0x02, 0x00, 0x7D, 0x22 ],
|
||||
[ 0x8A, 0x00, 0x7D, 0x22 ],
|
||||
[ 0x02, 0x00, 0x7D, 0x22 ],
|
||||
[ 0x02, 0x00, 0x7D, 0x22 ]
|
||||
],
|
||||
"voltage":3.3,
|
||||
|
|
|
|||
90
FlashGBX/config/fc_AGB_MSP54LV256.txt
Normal file
90
FlashGBX/config/fc_AGB_MSP54LV256.txt
Normal file
|
|
@ -0,0 +1,90 @@
|
|||
{
|
||||
"type":"AGB",
|
||||
"names":[
|
||||
"MXP54_16D_ERATH with MSP54LV256"
|
||||
],
|
||||
"flash_ids":[
|
||||
[ 0x02, 0x00, 0xBD, 0x22 ]
|
||||
],
|
||||
"voltage":3.3,
|
||||
"flash_size":0x2000000,
|
||||
"sector_size_from_cfi":true,
|
||||
"_reset_every":0x100000,
|
||||
"status_register_mask":0x40,
|
||||
"status_register_value":0x40,
|
||||
"chip_erase_timeout":300,
|
||||
"command_set":"AMD",
|
||||
"commands":{
|
||||
"reset":[
|
||||
[ 0, 0xF0 ]
|
||||
],
|
||||
"read_identifier":[
|
||||
[ 0xAAA, 0x69 ],
|
||||
[ 0x555, 0x96 ],
|
||||
[ 0xAAA, 0x50 ]
|
||||
],
|
||||
"read_cfi":[
|
||||
[ 0xAA, 0x58 ]
|
||||
],
|
||||
"sector_erase":[
|
||||
[ 0xAAA, 0x69 ],
|
||||
[ 0x555, 0x96 ],
|
||||
[ 0xAAA, 0x40 ],
|
||||
[ 0xAAA, 0x69 ],
|
||||
[ 0x555, 0x96 ],
|
||||
[ "SA", 0x30 ]
|
||||
],
|
||||
"sector_erase_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ "SA", 0xFFFF, 0xFFFF ]
|
||||
],
|
||||
"chip_erase":[
|
||||
[ 0xAAA, 0x69 ],
|
||||
[ 0x555, 0x96 ],
|
||||
[ 0xAAA, 0x40 ],
|
||||
[ 0xAAA, 0x69 ],
|
||||
[ 0x555, 0x96 ],
|
||||
[ 0xAAA, 0x10 ]
|
||||
],
|
||||
"chip_erase_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ 0, 0xFFFF, 0xFFFF ]
|
||||
],
|
||||
"buffer_write":[
|
||||
[ 0xAAA, 0x69 ],
|
||||
[ 0x555, 0x96 ],
|
||||
[ "SA", 0x26 ],
|
||||
[ "SA", "BS" ],
|
||||
[ "PA", "PD" ],
|
||||
[ "SA", 0x2A ]
|
||||
],
|
||||
"buffer_write_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ "SA", "PD", 0xFFFF ]
|
||||
],
|
||||
"single_write":[
|
||||
[ 0xAAA, 0x69 ],
|
||||
[ 0x555, 0x96 ],
|
||||
[ 0xAAA, 0x60 ],
|
||||
[ "PA", "PD" ]
|
||||
],
|
||||
"single_write_wait_for":[
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ],
|
||||
[ null, null, null ]
|
||||
]
|
||||
}
|
||||
}
|
||||
|
|
@ -11,6 +11,7 @@
|
|||
[ 0x20, 0x00, 0x7D, 0x00 ]
|
||||
],
|
||||
"voltage":3.3,
|
||||
"voltage_variants":true,
|
||||
"flash_size":0x400000,
|
||||
"start_addr":0,
|
||||
"first_bank":1,
|
||||
|
|
|
|||
|
|
@ -2,11 +2,13 @@
|
|||
"type":"DMG",
|
||||
"names":[
|
||||
"GBFlash RTC with MX29LV320EB",
|
||||
"GBFlash RTC with MX29LV320EB"
|
||||
"GBFlash RTC with MX29LV320EB",
|
||||
"ModRetro Chromatic Cartridge with S29JL032"
|
||||
],
|
||||
"flash_ids":[
|
||||
[ 0x01, 0x01, 0x7E, 0x7E ],
|
||||
[ 0xC2, 0xC2, 0xA8, 0xA8 ]
|
||||
[ 0xC2, 0xC2, 0xA8, 0xA8 ],
|
||||
[ 0x01, 0x01, 0x53, 0x53 ]
|
||||
],
|
||||
"voltage":5,
|
||||
"flash_size":0x400000,
|
||||
|
|
|
|||
|
|
@ -1,10 +1,12 @@
|
|||
{
|
||||
"type":"DMG",
|
||||
"names":[
|
||||
"insideGadgets 4 MiB (S29GL032M)"
|
||||
"insideGadgets 4 MiB (S29GL032M)",
|
||||
"ModRetro Chromatic Cartridge with IS29GL032"
|
||||
],
|
||||
"flash_ids":[
|
||||
[ 0x01, 0x01, 0x7E, 0x7E ]
|
||||
[ 0x01, 0x01, 0x7E, 0x7E ],
|
||||
[ 0x9D, 0x9D, 0x7E, 0x7E ]
|
||||
],
|
||||
"voltage":5,
|
||||
"flash_size":0x400000,
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
import zipfile, serial, struct, time, datetime
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
import zipfile, os, serial, struct, time, re, math
|
||||
from .pyside import QtCore, QtWidgets, QtGui, QDesktopWidget
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
import zipfile, serial, struct, time, random, hashlib, datetime
|
||||
try:
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
import zipfile, time, os, struct, serial, platform
|
||||
from serial import SerialException
|
||||
|
|
@ -422,7 +422,7 @@ try:
|
|||
verified = False
|
||||
|
||||
if verified is False:
|
||||
text = "The firmware update file is corrupted."
|
||||
text = "The firmware update file is corrupted or invalid."
|
||||
self.btnUpdate.setEnabled(True)
|
||||
self.btnClose.setEnabled(True)
|
||||
msgbox = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Critical, windowTitle="FlashGBX", text=text, standardButtons=QtWidgets.QMessageBox.Ok)
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
# pylint: disable=wildcard-import, unused-wildcard-import
|
||||
from .LK_Device import *
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
# pylint: disable=wildcard-import, unused-wildcard-import
|
||||
from .LK_Device import *
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
# pylint: disable=wildcard-import, unused-wildcard-import
|
||||
from .LK_Device import *
|
||||
|
|
|
|||
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
#
|
||||
# PySide abstraction layer contributed by J-Fox
|
||||
#
|
||||
|
|
|
|||
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
19
README.md
19
README.md
|
|
@ -1,8 +1,8 @@
|
|||
# FlashGBX (by Lesserkuma)
|
||||
|
||||
for Windows, Linux, macOS (→ [Download](https://github.com/lesserkuma/FlashGBX/releases))
|
||||
for Windows, Linux, macOS (→ [Download](https://github.com/Lesserkuma/FlashGBX/releases))
|
||||
|
||||
<img src="https://raw.githubusercontent.com/lesserkuma/FlashGBX/master/.github/01.png" alt="FlashGBX on Windows 11" width="500"><br><img src="https://raw.githubusercontent.com/lesserkuma/FlashGBX/master/.github/02.png" alt="GB Camera Album Viewer" width="500">
|
||||
<img src="https://raw.githubusercontent.com/Lesserkuma/FlashGBX/master/.github/01.png" alt="FlashGBX on Windows 11" width="500"><br><img src="https://raw.githubusercontent.com/Lesserkuma/FlashGBX/master/.github/02.png" alt="GB Camera Album Viewer" width="500">
|
||||
|
||||
## Introduction
|
||||
|
||||
|
|
@ -108,6 +108,7 @@ for Windows, Linux, macOS (→ [Download](https://github.com/lesserkuma/FlashGBX
|
|||
- insideGadgets 4 MiB (2× 2 MiB), 32 KiB FRAM, MBC5
|
||||
- insideGadgets MegaDuck 32K
|
||||
- ModRetro Chromatic Cartridge with 39VF1681
|
||||
- ModRetro Chromatic Cartridge with IS29GL032
|
||||
- Mr Flash 64M
|
||||
- Sillyhatday MBC5-DUAL-FLASH-4/8MB
|
||||
- Squareboi 4 MiB (2× 2 MiB)
|
||||
|
|
@ -185,6 +186,7 @@ for Windows, Linux, macOS (→ [Download](https://github.com/lesserkuma/FlashGBX
|
|||
- SD007_BV5_V3 with AM29LV160MB
|
||||
- SD007_K8D3216_32M with MX29LV160CT
|
||||
- SD007_T40_48BALL_71_TV_TS28 with M29W640
|
||||
- SD007_T40_6401B\*CD_71_TS28 with 39VF6401B
|
||||
- SD007_T40_64BALL_S71_TV_TS28 with TC58FVB016FT-85
|
||||
- SD007_T40_64BALL_SOJ28 with 29LV016T
|
||||
- SD007_T40_64BALL_TSOP28 with 29LV016T
|
||||
|
|
@ -276,6 +278,8 @@ for Windows, Linux, macOS (→ [Download](https://github.com/lesserkuma/FlashGBX
|
|||
- M6MGJ927 (no PCB text)
|
||||
- MSP54LV512 (no PCB text)
|
||||
- MX29GL128EHT2I and ALTERA CPLD
|
||||
- MXP54_16D_046 with MSP54LV256
|
||||
- MXP54_16D_ERATH with MSP54LV256
|
||||
- SUN100S_MSP54XXX with MSP54LV100
|
||||
- Unknown 29LV320 variant (no PCB text)
|
||||
|
||||
|
|
@ -287,19 +291,20 @@ Many different reproduction cartridges share their flash chip command set, so ev
|
|||
|
||||
### Pre-compiled binaries and packages
|
||||
|
||||
Available in the GitHub [Releases](https://github.com/lesserkuma/FlashGBX/releases) section are pre-compiled downloads available for:
|
||||
Available in the GitHub [Releases](https://github.com/Lesserkuma/FlashGBX/releases) section are pre-compiled downloads available for:
|
||||
|
||||
* **Windows (64-bit)** *(Windows 8 or newer)*
|
||||
* Setup: An installer that will add the application to the start menu and optionally create a desktop icon
|
||||
* Portable: Have everything in one place including the config files
|
||||
|
||||
* **Linux**
|
||||
* Pre-made packages are contributed by JJ-Fox [here](https://github.com/JJ-Fox/FlashGBX-Linux-builds/releases/latest).
|
||||
* Ubuntu (.deb file): Install using `dpkg -i /path/to/FlashGBX_x.x_Ubuntu-all.deb`.
|
||||
* Other distributions: Pre-made Linux packages are available at [JJ-Fox’s repository](https://github.com/JJ-Fox/FlashGBX-Linux-builds/releases/latest).
|
||||
|
||||
* **macOS** *(Monterey 12 or newer)*
|
||||
* x86-64/arm64 (.dmg file): Install by opening the .dmg file and copying over the “FlashGBX” application to the desktop.<br>If it doesn’t run, it probably got quarantined during download. Run the following command in a Terminal window to unquarantine it: `xattr -d com.apple.quarantine /path/to/FlashGBX.app`.<br>*(Based on a contribution by [Cliffback](https://github.com/Cliffback))*
|
||||
* x86-64/arm64 (.dmg file): Install by opening the .dmg file and copying over the “FlashGBX” application to the desktop.<br>If it doesn’t run, it probably got quarantined due to the lack of a Apple Developer Program certificate. Right-click the extracted FlashGBX icon, choose “Open Terminal at Folder” and enter this command to unquarantine it: `xattr -d com.apple.quarantine ../FlashGBX.app`.
|
||||
|
||||
*(If you have a Joey Jr and use macOS, please run the [Joey Jr Firmware Updater](https://github.com/lesserkuma/JoeyJr_FWUpdater) before using FlashGBX.)*
|
||||
*(If you have a Joey Jr and use macOS, please run the [Joey Jr Firmware Updater](https://github.com/Lesserkuma/JoeyJr_FWUpdater) before using FlashGBX.)*
|
||||
|
||||
### Run via Python
|
||||
|
||||
|
|
@ -385,7 +390,7 @@ Thanks to the No-Intro project for their game databases which FlashGBX’s datab
|
|||
|
||||
## Third Party Notices and Licenses
|
||||
|
||||
Please view the <a href="https://github.com/lesserkuma/FlashGBX/blob/master/Third%20Party%20Notices.md">Third Party Notices</a>.
|
||||
Please view the <a href="https://github.com/Lesserkuma/FlashGBX/blob/master/Third%20Party%20Notices.md">Third Party Notices</a>.
|
||||
|
||||
## DISCLAIMER
|
||||
|
||||
|
|
|
|||
2
run.py
2
run.py
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
# Note: This file runs FlashGBX in portable mode.
|
||||
|
||||
|
|
|
|||
10
setup.py
10
setup.py
|
|
@ -1,6 +1,6 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
# FlashGBX
|
||||
# Author: Lesserkuma (github.com/lesserkuma)
|
||||
# Author: Lesserkuma (github.com/Lesserkuma)
|
||||
|
||||
import setuptools
|
||||
|
||||
|
|
@ -8,10 +8,10 @@ with open("README.md", "r", encoding="utf-8") as fh: long_description = fh.read(
|
|||
|
||||
setuptools.setup(
|
||||
name="FlashGBX",
|
||||
version="4.4",
|
||||
version="4.5",
|
||||
author="Lesserkuma",
|
||||
description="Reads and writes Game Boy and Game Boy Advance cartridge data",
|
||||
url="https://github.com/lesserkuma/FlashGBX",
|
||||
url="https://github.com/Lesserkuma/FlashGBX",
|
||||
packages=setuptools.find_packages(),
|
||||
install_requires=['pyserial>=3.5', 'Pillow', 'setuptools', 'requests', 'python-dateutil'],
|
||||
extras_require={
|
||||
|
|
@ -30,8 +30,8 @@ setuptools.setup(
|
|||
'Intended Audience :: Developers',
|
||||
],
|
||||
project_urls={
|
||||
'Source': 'https://github.com/lesserkuma/FlashGBX/',
|
||||
'Tracker': 'https://github.com/lesserkuma/FlashGBX/issues',
|
||||
'Source': 'https://github.com/Lesserkuma/FlashGBX/',
|
||||
'Tracker': 'https://github.com/Lesserkuma/FlashGBX/issues',
|
||||
},
|
||||
entry_points={
|
||||
'console_scripts': (
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user