This commit is contained in:
Lesserkuma
2023-04-18 13:24:36 +02:00
parent be37fcf1d6
commit 47a334a143
9 changed files with 50 additions and 45 deletions

View File

@@ -1,4 +1,9 @@
# Release notes
### v3.26 (released 2023-04-18)
- Fixed a bug that made exporting Game Boy Camera pictures with a frame not work *(thanks Ell)*
- Fixed a bug with Game Boy ROM write verification on sectors smaller than 0x4000 bytes *(thanks KOOORAY)*
- Improved auto-detect for the BennVenn MBC3000 RTC cart
### v3.25 (released 2023-04-14)
- Bundles GBxCart RW v1.4/v1.4a firmware version R41+L9 (minor improvements)
- Fixed an issue with the Game Boy Camera Album Viewer *(thanks CodyWick13)*

View File

@@ -1017,7 +1017,7 @@ class FlashGBX_GUI(QtWidgets.QWidget):
if dontShowAgainCameraSavePopup: self.SETTINGS.setValue("SkipCameraSavePopup", "enabled")
if answer == QtWidgets.QMessageBox.Yes:
self.CAMWIN = None
self.CAMWIN = PocketCameraWindow(self, icon=self.windowIcon(), file=self.CONN.INFO["last_path"], config_path=Util.CONFIG_PATH)
self.CAMWIN = PocketCameraWindow(self, icon=self.windowIcon(), file=self.CONN.INFO["last_path"], config_path=Util.CONFIG_PATH, app_path=Util.APP_PATH)
self.CAMWIN.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
self.CAMWIN.setModal(True)
self.CAMWIN.run()
@@ -2690,7 +2690,7 @@ class FlashGBX_GUI(QtWidgets.QWidget):
data = self.CONN.INFO["data"]
self.CAMWIN = None
self.CAMWIN = PocketCameraWindow(self, icon=self.windowIcon(), file=data, config_path=Util.CONFIG_PATH)
self.CAMWIN = PocketCameraWindow(self, icon=self.windowIcon(), file=data, config_path=Util.CONFIG_PATH, app_path=Util.APP_PATH)
self.CAMWIN.setAttribute(QtCore.Qt.WA_DeleteOnClose, True)
self.CAMWIN.setModal(True)
self.CAMWIN.run()

View File

@@ -17,6 +17,7 @@ class PocketCameraWindow(QtWidgets.QDialog):
CUR_EXPORT_PATH = "."
CUR_PC = None
CUR_PALETTE = 3
APP_PATH = "."
CONFIG_PATH = "."
APP = None
PALETTES = [
@@ -28,12 +29,13 @@ class PocketCameraWindow(QtWidgets.QDialog):
[ 240, 240, 240, 134, 200, 100, 58, 96, 132, 30, 30, 30 ], # Game Boy Color (USA/EUR)
]
def __init__(self, app, file=None, icon=None, config_path="."):
def __init__(self, app, file=None, icon=None, config_path=".", app_path="."):
QtWidgets.QDialog.__init__(self)
self.setAcceptDrops(True)
if icon is not None: self.setWindowIcon(QtGui.QIcon(icon))
self.CUR_FILE = file
self.CONFIG_PATH = config_path
self.APP_PATH = app_path
self.setWindowTitle("FlashGBX GB Camera Album Viewer")
self.setWindowFlags((self.windowFlags() | QtCore.Qt.MSWindowsFixedSizeDialogHint) & ~QtCore.Qt.WindowContextHelpButtonHint)
@@ -343,7 +345,7 @@ class PocketCameraWindow(QtWidgets.QDialog):
frame = True
own_frame = self.CONFIG_PATH + "/pc_frame.png"
if not os.path.exists(own_frame):
shutil.copy(self.APP.APP_PATH + "/res/pc_frame.png", own_frame)
shutil.copy(self.APP_PATH + "/res/pc_frame.png", own_frame)
with open(own_frame, "rb") as f: frame = f.read()
if index == 31: frame = False # last seen image

View File

@@ -7,9 +7,9 @@ from enum import Enum
# Common constants
APPNAME = "FlashGBX"
VERSION_PEP440 = "3.25"
VERSION_PEP440 = "3.26"
VERSION = "v{:s}".format(VERSION_PEP440)
VERSION_TIMESTAMP = 1681495829
VERSION_TIMESTAMP = 1681817120
DEBUG = False
DEBUG_LOG = []
APP_PATH = ""
@@ -809,4 +809,4 @@ def dprint(*args, **kwargs):
DEBUG_LOG = DEBUG_LOG[-32768:]
if DEBUG:
msg = "{:s}{:s}".format(ANSI.CLEAR_LINE, msg)
#print(msg)
print(msg)

View File

@@ -17,7 +17,7 @@ class GbxDevice:
DEVICE_NAME = "GBxCart RW"
DEVICE_MIN_FW = 1
DEVICE_MAX_FW = 9
DEVICE_LATEST_FW_TS = { 4:1619427330, 5:1681395695, 6:1681395696 }
DEVICE_LATEST_FW_TS = { 4:1681739002, 5:1681395695, 6:1681395696 }
DEVICE_CMD = {
"NULL":0x30,
@@ -114,7 +114,7 @@ class GbxDevice:
FAST_READ = False
SKIPPING = False
BAUDRATE = 1000000
MAX_BUFFER_LEN = 0x2000
MAX_BUFFER_LEN = 0x800
DEVICE_TIMEOUT = 0.75
WRITE_DELAY = False
READ_ERRORS = 0
@@ -144,14 +144,12 @@ class GbxDevice:
if not self.LoadFirmwareVersion() and max_baud >= 1700000:
dev.close()
self.BAUDRATE = 1700000
self.MAX_BUFFER_LEN = 0x2000
dev = serial.Serial(ports[i], self.BAUDRATE, timeout=0.1)
self.DEVICE = dev
if not self.LoadFirmwareVersion():
if not self.LoadFirmwareVersion() or self.FW["pcb_ver"] not in (5, 6, 101):
dev.close()
self.DEVICE = None
self.BAUDRATE = 1000000
self.MAX_BUFFER_LEN = 0x100
continue
elif max_baud >= 1700000 and self.FW["pcb_ver"] in (5, 6, 101) and self.BAUDRATE < 1700000:
self.ChangeBaudRate(baudrate=1700000)
@@ -176,15 +174,17 @@ class GbxDevice:
self.DEVICE = None
conn_msg.append([3, "The GBxCart RW device on port " + ports[i] + " requires a firmware update to work with this software. Please try again after updating it to version L" + str(self.DEVICE_MIN_FW) + " or higher.<br><br>Firmware updates are available at <a href=\"https://www.gbxcart.com/\">https://www.gbxcart.com/</a>."])
continue
#elif self.FW["fw_ver"] < self.DEVICE_MAX_FW:
# conn_msg.append([1, "The GBxCart RW device on port " + ports[i] + " is running an older firmware version. Please consider updating to version L" + str(self.DEVICE_MAX_FW) + " to make use of the latest features.<br><br>Firmware updates are available at <a href=\"https://www.gbxcart.com/\">https://www.gbxcart.com/</a>."])
elif self.FW["fw_ver"] > self.DEVICE_MAX_FW:
elif self.FW["fw_ts"] > self.DEVICE_LATEST_FW_TS[self.FW["pcb_ver"]]:
conn_msg.append([0, "Note: The GBxCart RW device on port " + ports[i] + " is running a firmware version that is newer than what this version of FlashGBX was developed to work with, so errors may occur."])
if (self.FW["pcb_ver"] not in (4, 5, 6, 101)): # only the v1.3, v1.4, v1.4a, Mini v1.1 PCB revisions are supported
if self.FW["pcb_ver"] not in (4, 5, 6, 101): # only the v1.3, v1.4, v1.4a, Mini v1.1 PCB revisions are supported
dev.close()
self.DEVICE = None
continue
elif self.FW["pcb_ver"] in (5, 6, 101) and self.BAUDRATE > 1000000:
self.MAX_BUFFER_LEN = 0x2000
else:
self.MAX_BUFFER_LEN = 0x800
conn_msg.append([0, "For help please visit the insideGadgets Discord: https://gbxcart.com/discord"])
@@ -213,7 +213,6 @@ class GbxDevice:
self.DEVICE.reset_output_buffer()
self._write(self.DEVICE_CMD["OFW_PCB_VER"])
temp = self.DEVICE.read(1)
#if len(temp) == 0: return False
pcb = temp[0]
if pcb == b'': return False
self._write(self.DEVICE_CMD["OFW_FW_VER"])
@@ -255,12 +254,10 @@ class GbxDevice:
self._write(self.DEVICE_CMD["OFW_USART_1_7M_SPEED"])
self.Close()
self.BAUDRATE = baudrate
self.MAX_BUFFER_LEN = 0x2000
elif baudrate == 1000000:
self._write(self.DEVICE_CMD["OFW_USART_1_0M_SPEED"])
self.Close()
self.BAUDRATE = baudrate
self.MAX_BUFFER_LEN = 0x100
def CanSetVoltageManually(self):
return False
@@ -377,8 +374,10 @@ class GbxDevice:
return self.FW["pcb_ver"] in (4, 5, 6)
def FirmwareUpdateAvailable(self):
if self.FW["pcb_ver"] not in (5, 6): return False
return (self.FW["pcb_ver"] in (4, 5, 6) and self.FW["fw_ts"] < self.DEVICE_LATEST_FW_TS[self.FW["pcb_ver"]])
if self.FW["pcb_ver"] not in (4, 5, 6): return False
if (self.FW["pcb_ver"] in (4, 5, 6) and self.FW["fw_ts"] < self.DEVICE_LATEST_FW_TS[self.FW["pcb_ver"]]):
if self.FW["pcb_ver"] == 4: self.FW_UPDATE_REQ = True
return True
def GetFirmwareUpdaterClass(self):
if self.FW["pcb_ver"] == 4: # v1.3
@@ -1115,7 +1114,10 @@ class GbxDevice:
buffer += temp
if not self.NO_PROG_UPDATE:
self.SetProgress({"action":"READ", "bytes_added":len(temp)})
if self.MODE == "DMG":
self._set_fw_variable("DMG_READ_CS_PULSE", 0)
return buffer
def ReadRAM_MBC7(self, address, length):
@@ -1168,6 +1170,8 @@ class GbxDevice:
buffer.append(data)
self.SetProgress({"action":"UPDATE_POS", "abortable":False, "pos":i+1})
self._set_fw_variable("DMG_READ_CS_PULSE", 0)
self.NO_PROG_UPDATE = npu
return buffer
@@ -2128,11 +2132,8 @@ class GbxDevice:
end_bank = math.ceil((buffer_pos + args["bl_size"]) / rom_bank_size)
rom_banks = end_bank
dprint("start_address=0x{:X}, end_address=0x{:X}, start_bank=0x{:X}, rom_banks=0x{:X}".format(start_address, end_address, start_bank, rom_banks))
dprint("start_address=0x{:X}, end_address=0x{:X}, start_bank=0x{:X}, rom_banks=0x{:X}, buffer_len=0x{:X}, max_length=0x{:X}".format(start_address, end_address, start_bank, rom_banks, buffer_len, max_length))
bank = start_bank
#for bank in range(0, rom_banks):
while bank < rom_banks:
# ↓↓↓ Switch ROM bank
if self.MODE == "DMG":
@@ -2141,17 +2142,16 @@ class GbxDevice:
self._write(self.DEVICE_CMD["DMG_MBC_RESET"], wait=True)
(start_address, bank_size) = _mbc.SelectBankROM(bank)
end_address = start_address + bank_size
buffer_len = _mbc.GetROMBankSize()
buffer_len = min(buffer_len, _mbc.GetROMBankSize())
if "verify_write" in args:
buffer_len = min(buffer_len, bank_size)
#if "start_addr" in flashcart.CONFIG and bank == 0: start_address = flashcart.CONFIG["start_addr"]
buffer_len = min(buffer_len, bank_size, len(args["verify_write"]))
end_address = start_address + bank_size
start_address += (buffer_pos % rom_bank_size)
if end_address > start_address + args["verify_len"]:
end_address = start_address + args["verify_len"]
# dprint("{:X}/{:X}/{:X}".format(start_address, bank_size, buffer_len))
elif self.MODE == "AGB":
if "verify_write" in args:
buffer_len = min(buffer_len, len(args["verify_write"]))
if "flash_bank_select_type" in cart_type and cart_type["flash_bank_select_type"] > 0:
flashcart.SelectBankROM(bank)
temp = end_address - start_address
@@ -2163,8 +2163,6 @@ class GbxDevice:
pos = start_address
lives = 20
# dprint("pos_total=0x{:X}, start_address=0x{:X}, end_address=0x{:X}".format(pos_total, start_address, end_address))
while pos < end_address:
temp = bytearray()
if self.CANCEL:
@@ -2184,26 +2182,26 @@ class GbxDevice:
temp = self.ReadROM_3DMemory(address=pos, length=buffer_len, max_length=max_length)
else:
if self.FW["fw_ver"] >= 9 and "verify_write" in args and (self.MODE != "AGB" or args["verify_base_pos"] > 0xC9):
# Verify mode (by checksum)
dprint("Checksum verification (verify_base_pos=0x{:X}, pos=0x{:X}, pos_total=0x{:X}, buffer_len=0x{:X})".format(args["verify_base_pos"], pos, pos_total, buffer_len))
# Verify mode (by CRC32)
dprint("CRC32 verification (verify_base_pos=0x{:X}, pos=0x{:X}, pos_total=0x{:X}, buffer_len=0x{:X})".format(args["verify_base_pos"], pos, pos_total, buffer_len))
if self.MODE == "DMG":
self._set_fw_variable("ADDRESS", pos)
elif self.MODE == "AGB":
self._set_fw_variable("ADDRESS", pos >> 1)
self._write(self.DEVICE_CMD["CALC_CRC32"])
self._write(bytearray(struct.pack(">I", buffer_len)))
checksum_expected = zlib.crc32(args["verify_write"][pos_total:pos_total+buffer_len])
checksum_calculated = struct.unpack(">I", self._read(4))[0]
dprint("Expected Checksum: 0x{:X}".format(checksum_expected))
dprint("Calculated Checksum: 0x{:X}".format(checksum_calculated))
if checksum_expected == checksum_calculated:
crc32_expected = zlib.crc32(args["verify_write"][pos_total:pos_total+buffer_len])
crc32_calculated = struct.unpack(">I", self._read(4))[0]
dprint("Expected CRC32: 0x{:X}".format(crc32_expected))
dprint("Calculated CRC32: 0x{:X}".format(crc32_calculated))
if crc32_expected == crc32_calculated:
pos += buffer_len
pos_total += buffer_len
dprint("Verification successful between 0x{:X} and 0x{:X}".format(pos_total-buffer_len, pos_total))
dprint("CRC32 verification successful between 0x{:X} and 0x{:X}".format(pos_total-buffer_len, pos_total))
self.SetProgress({"action":"UPDATE_POS", "pos":args["verify_from"]+pos_total})
continue
else:
dprint("Mismatch during verification between 0x{:X} and 0x{:X}".format(pos_total, pos_total+buffer_len))
dprint("Mismatch during CRC32 verification between 0x{:X} and 0x{:X}".format(pos_total, pos_total+buffer_len))
return pos_total
else:
# Normal read
@@ -3468,7 +3466,7 @@ class GbxDevice:
if self.MODE == "DMG" and _mbc.HasFlashBanks(): _mbc.SelectBankFlash(bank)
time.sleep(delay)
if self.DEVICE is None:
raise ConnectionAbortedError("An critical connection error occured while writing 0x{:X} bytes at position 0x{:X} ({:s}). Please re-connect the device and try again from the beginning.".format(buffer_len, buffer_pos, Util.formatFileSize(size=buffer_pos, asInt=False)))
raise ConnectionAbortedError("A critical connection error occured while writing 0x{:X} bytes at position 0x{:X} ({:s}). Please re-connect the device and try again from the beginning.".format(buffer_len, buffer_pos, Util.formatFileSize(size=buffer_pos, asInt=False)))
self.CANCEL_ARGS = {}
self.CANCEL = False

Binary file not shown.

Binary file not shown.

View File

@@ -301,7 +301,7 @@ Many different reproduction cartridges share their flash chip command set, so ev
The author would like to thank the following very kind people for their help, contributions or documentation (in alphabetical order):
2358, 90sFlav, AcoVanConis, AdmirtheSableye, AlexiG, ALXCO-Hardware, AndehX, antPL, bbsan, BennVenn, ccs21, ClassicOldSong, CodyWick13, Corborg, crizzlycruz, Därk, Davidish, DevDavisNunez, Diddy_Kong, djedditt, Dr-InSide, dyf2007, easthighNerd, EchelonPrime, edo999, EmperorOfTigers, endrift, Erba Verde, ethanstrax, eveningmoose, Falknör, FerrantePescara, frarees, Frost Clock, gboh, gekkio, Godan, Grender, HDR, Herax, Hiccup, hiks, howie0210, iamevn, Icesythe7, Jayro, Jenetrix, JFox, joyrider3774, JS7457, julgr, Kaede, kscheel, kyokohunter, litlemoran, LovelyA72, Luca DS, LucentW, manuelcm1, marv17, metroid-maniac, Mr_V, orangeglo, paarongiroux, Paradoxical, Rairch, Raphaël BOICHOT, redalchemy, RetroGorek, RevZ, s1cp, Satumox, Sgt.DoudouMiel, Shinichi999, sillyhatday, Sithdown, skite2001, Smelly-Ghost, Stitch, Super Maker, t5b6_de, Tauwasser, Timville, twitnic, velipso, Veund, voltagex, Voultar, Wkr, x7l7j8cc, xactoes, Zeii, Zelante, zvxr
2358, 90sFlav, AcoVanConis, AdmirtheSableye, AlexiG, ALXCO-Hardware, AndehX, antPL, bbsan, BennVenn, ccs21, ClassicOldSong, CodyWick13, Corborg, crizzlycruz, Därk, Davidish, DevDavisNunez, Diddy_Kong, djedditt, Dr-InSide, dyf2007, easthighNerd, EchelonPrime, edo999, Ell, EmperorOfTigers, endrift, Erba Verde, ethanstrax, eveningmoose, Falknör, FerrantePescara, frarees, Frost Clock, gboh, gekkio, Godan, Grender, HDR, Herax, Hiccup, hiks, howie0210, iamevn, Icesythe7, Jayro, Jenetrix, JFox, joyrider3774, JS7457, julgr, Kaede, KOOORAY, kscheel, kyokohunter, litlemoran, LovelyA72, Luca DS, LucentW, manuelcm1, marv17, metroid-maniac, Mr_V, orangeglo, paarongiroux, Paradoxical, Rairch, Raphaël BOICHOT, redalchemy, RetroGorek, RevZ, s1cp, Satumox, Sgt.DoudouMiel, Shinichi999, sillyhatday, Sithdown, skite2001, Smelly-Ghost, Stitch, Super Maker, t5b6_de, Tauwasser, Timville, twitnic, velipso, Veund, voltagex, Voultar, Wkr, x7l7j8cc, xactoes, Zeii, Zelante, zvxr
## DISCLAIMER

View File

@@ -4,7 +4,7 @@ with open("README.md", "r", encoding="utf-8") as fh: long_description = fh.read(
setuptools.setup(
name="FlashGBX",
version="3.25",
version="3.26",
author="Lesserkuma",
description="Reads and writes Game Boy and Game Boy Advance cartridge data using the GBxCart RW by insideGadgets",
url="https://github.com/lesserkuma/FlashGBX",