This commit is contained in:
Lesserkuma 2022-07-26 18:50:26 +02:00
parent 14d401a3f9
commit 6a76a388ca
17 changed files with 3415 additions and 3195 deletions

View File

@ -1,4 +1,13 @@
# Release notes
### v3.16 (released 2022-07-26)
- Added support for 256M29EWH (no PCB text) *(thanks Diddy_Kong)*
- Added support for a new insideGadgets 4 MB flash cartridge *(thanks AlexiG)*
- Added support for Ferrante Crafts cart 32 KB V2 *(thanks FerrantePescara)*
- Bundles GBxCart RW v1.4 firmware version R37+L7 (improves support for some Game Boy flash cartridges)
- Updated the Game Boy Advance lookup database for save types, ROM sizes and checksums
- Added an option for manually specifying the device port to use via command line argument `--device-port`
- Support added for Pocket Camera save data files made using 2bit PXLR Studio
### v3.15 (released 2022-07-05)
- Improved support for several flash cartridge types
- Confirmed support for the Catskull 32k Gameboy Flash Cart *(thanks CodyWick13)*

View File

@ -142,7 +142,7 @@ def main(portableMode=False):
ap_cli2.add_argument("--save-filename-add-datetime", action="store_true", help="adds a timestamp to the file name of save data backups")
ap_cli2.add_argument("--gbcamera-palette", choices=["grayscale", "dmg", "sgb", "cgb1", "cgb2", "cgb3"], type=str.lower, default="grayscale", help="sets the palette of pictures extracted from Game Boy Camera saves")
ap_cli2.add_argument("--gbcamera-outfile-format", choices=["png", "bmp", "gif", "jpg"], type=str.lower, default="png", help="sets the file format of saved pictures extracted from Game Boy Camera saves")
ap_cli2.add_argument("--fwupdate-port", help="override device port for the firmware updater", default=None)
ap_cli2.add_argument("--device-port", help="override device port", default=None)
args = parser.parse_args()
if "appdata" in cp:

View File

@ -77,7 +77,7 @@ class FlashGBX_CLI():
self.ARGS["called_with_args"] = True
if args.action is None or args.action not in ("gbcamera-extract", "fwupdate-gbxcartrw"):
if not self.FindDevices():
if not self.FindDevices(port=args.device_port):
print("No devices found.")
return
else:
@ -118,7 +118,7 @@ class FlashGBX_CLI():
return
if args.action == "fwupdate-gbxcartrw":
self.UpdateFirmwareGBxCartRW(pcb=5, port=args.fwupdate_port)
self.UpdateFirmwareGBxCartRW(pcb=5, port=args.device_port)
return 0
elif args.mode is None:
@ -333,26 +333,24 @@ class FlashGBX_CLI():
elif self.CONN.INFO["last_action"] == 2: # Backup RAM
self.CONN.INFO["last_action"] = 0
if not "debug" in self.ARGS and self.CONN.INFO["transferred"] == 131072: # 128 KB
with open(self.CONN.INFO["last_path"], "rb") as file: temp = file.read()
if temp[0x1FFB1:0x1FFB6] == b'Magic' and not self.ARGS["called_with_args"]:
answer = input("Game Boy Camera save data was detected.\nWould you like to extract all pictures to “{:s}” now? [Y/n]: ".format(Util.formatPathOS(os.path.abspath(os.path.splitext(self.CONN.INFO["last_path"])[0]), end_sep=True) + "IMG_PC**.{:s}".format(self.ARGS["argparsed"].gbcamera_outfile_format))).strip().lower()
if answer != "n":
pc = PocketCamera()
if pc.LoadFile(self.CONN.INFO["last_path"]) != False:
palettes = [ "grayscale", "dmg", "sgb", "cgb1", "cgb2", "cgb3" ]
pc.SetPalette(palettes.index(self.ARGS["argparsed"].gbcamera_palette))
file = os.path.splitext(self.CONN.INFO["last_path"])[0] + "/IMG_PC00.png"
if os.path.isfile(os.path.dirname(file)):
print("Cant save pictures at location “{:s}”.".format(os.path.abspath(os.path.dirname(file))))
return
if not os.path.isdir(os.path.dirname(file)):
os.makedirs(os.path.dirname(file))
for i in range(0, 32):
file = os.path.splitext(self.CONN.INFO["last_path"])[0] + "/IMG_PC{:02d}".format(i) + "." + self.ARGS["argparsed"].gbcamera_outfile_format
pc.ExportPicture(i, file, scale=1)
print("The pictures were extracted.")
print("")
if not "debug" in self.ARGS and self.CONN.INFO["mapper_raw"] == 252 and self.CONN.INFO["transferred"] == 131072: # Pocket Camera / 128 KB: # 128 KB
answer = input("Would you like to extract Game Boy Camera pictures to “{:s}” now? [Y/n]: ".format(Util.formatPathOS(os.path.abspath(os.path.splitext(self.CONN.INFO["last_path"])[0]), end_sep=True) + "IMG_PC**.{:s}".format(self.ARGS["argparsed"].gbcamera_outfile_format))).strip().lower()
if answer != "n":
pc = PocketCamera()
if pc.LoadFile(self.CONN.INFO["last_path"]) != False:
palettes = [ "grayscale", "dmg", "sgb", "cgb1", "cgb2", "cgb3" ]
pc.SetPalette(palettes.index(self.ARGS["argparsed"].gbcamera_palette))
file = os.path.splitext(self.CONN.INFO["last_path"])[0] + "/IMG_PC00.png"
if os.path.isfile(os.path.dirname(file)):
print("Cant save pictures at location “{:s}”.".format(os.path.abspath(os.path.dirname(file))))
return
if not os.path.isdir(os.path.dirname(file)):
os.makedirs(os.path.dirname(file))
for i in range(0, 32):
file = os.path.splitext(self.CONN.INFO["last_path"])[0] + "/IMG_PC{:02d}".format(i) + "." + self.ARGS["argparsed"].gbcamera_outfile_format
pc.ExportPicture(i, file, scale=1)
print("The pictures were extracted.")
print("")
print("The save data backup is complete!")
@ -367,11 +365,11 @@ class FlashGBX_CLI():
else:
self.CONN.INFO["last_action"] = 0
def FindDevices(self, connectToFirst=False):
def FindDevices(self, port=None):
global hw_devices
for hw_device in hw_devices:
dev = hw_device.GbxDevice()
ret = dev.Initialize(self.FLASHCARTS, max_baud=1700000)
ret = dev.Initialize(self.FLASHCARTS, max_baud=1700000, port=port)
if ret is False:
self.CONN = None
elif isinstance(ret, list):

View File

@ -255,7 +255,8 @@ class FlashGBX_GUI(QtWidgets.QWidget):
elif config_ret[i][0] == 3:
QtWidgets.QMessageBox.critical(self, "{:s} {:s}".format(APPNAME, VERSION), config_ret[i][1], QtWidgets.QMessageBox.Ok)
QtCore.QTimer.singleShot(1, lambda: [ self.UpdateCheck(), self.FindDevices() ])
QtCore.QTimer.singleShot(1, lambda: [ self.UpdateCheck(), self.FindDevices(port=args["argparsed"].device_port) ])
def GuiCreateGroupBoxDMGCartInfo(self):
self.grpDMGCartridgeInfo = QtWidgets.QGroupBox("Game Boy Cartridge Information")
@ -680,7 +681,7 @@ class FlashGBX_GUI(QtWidgets.QWidget):
return True
return False
def FindDevices(self, connectToFirst=False):
def FindDevices(self, connectToFirst=False, port=None):
if self.CONN is not None:
self.DisconnectDevice()
self.lblDevice.setText("Searching...")
@ -693,7 +694,7 @@ class FlashGBX_GUI(QtWidgets.QWidget):
global hw_devices
for hw_device in hw_devices:
dev = hw_device.GbxDevice()
ret = dev.Initialize(self.FLASHCARTS, max_baud=1700000)
ret = dev.Initialize(self.FLASHCARTS, max_baud=1700000, port=port)
if ret is False:
self.CONN = None
elif isinstance(ret, list):
@ -910,11 +911,9 @@ class FlashGBX_GUI(QtWidgets.QWidget):
dontShowAgainCameraSavePopup = str(self.SETTINGS.value("SkipCameraSavePopup", default="disabled")).lower() == "enabled"
if not dontShowAgainCameraSavePopup:
if self.CONN.INFO["transferred"] == 131072: # 128 KB
with open(self.CONN.INFO["last_path"], "rb") as file: temp = file.read()
if temp[0x1FFB1:0x1FFB6] == b'Magic':
if self.CONN.INFO["mapper_raw"] == 252 and self.CONN.INFO["transferred"] == 131072: # Pocket Camera / 128 KB
cbCameraSavePopup = QtWidgets.QCheckBox("Dont show this message again", checked=dontShowAgain)
msgboxCameraPopup = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Question, windowTitle="{:s} {:s}".format(APPNAME, VERSION), text="Game Boy Camera save data was detected.\nWould you like to load it with the GB Camera Viewer now?")
msgboxCameraPopup = QtWidgets.QMessageBox(parent=self, icon=QtWidgets.QMessageBox.Question, windowTitle="{:s} {:s}".format(APPNAME, VERSION), text="Would you like to load your save data with the GB Camera Viewer now?")
msgboxCameraPopup.setStandardButtons(QtWidgets.QMessageBox.Yes | QtWidgets.QMessageBox.No)
msgboxCameraPopup.setDefaultButton(QtWidgets.QMessageBox.Yes)
msgboxCameraPopup.setCheckBox(cbCameraSavePopup)

View File

@ -930,7 +930,7 @@ class DMG_TAMA5(DMG_MBC):
dprint("Enabling TAMA5")
lives = 20
while (tama5_check & 3) != 1:
dprint("Current value is 0x{:X}, now writing 0xA001=0x{:X}".format(tama5_check, Util.TAMA5_REG.ENABLE.value))
dprint("- Current value is 0x{:X}, now writing 0xA001=0x{:X}".format(tama5_check, Util.TAMA5_REG.ENABLE.value))
self.CART_WRITE_FNCPTR(0xA001, Util.TAMA5_REG.ENABLE.value)
tama5_check = self.CartRead(0xA000)
time.sleep(0.1)

View File

@ -32,18 +32,20 @@ class PocketCamera:
if os.path.getsize(savefile) != 128*1024: return False
with open(savefile, "rb") as file: self.DATA = file.read()
if self.DATA[0x1FFB1:0x1FFB6] != b'Magic':
self.DATA = None
return False
# if self.DATA[0x1FFB1:0x1FFB6] != b'Magic':
# self.DATA = None
# return False
order_raw = self.DATA[0x11D7:0x11F5]
order = [None] * 30
deleted = []
seen_indicies = []
for i in range(0, 30):
if order_raw[i] == 0xFF:
if order_raw[i] == 0xFF or order_raw[i] in seen_indicies:
deleted.append(i)
else:
order[order_raw[i]] = i
seen_indicies.append(order_raw[i])
while None in order: order.remove(None)
order.extend(deleted)

View File

@ -7,7 +7,7 @@ from enum import Enum
# Common constants
APPNAME = "FlashGBX"
VERSION_PEP440 = "3.15"
VERSION_PEP440 = "3.16"
VERSION = "v{:s}".format(VERSION_PEP440)
DEBUG = False

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,78 @@
{
"type":"DMG",
"names":[
"256M29EWH (no PCB text)"
],
"flash_ids":[
[ 0x8A, 0x8A, 0x7D, 0x7D ]
],
"voltage":3.3,
"voltage_variants":true,
"flash_size":0x2000000,
"start_addr":0,
"first_bank":1,
"chip_erase_timeout":120,
"sector_size_from_cfi":true,
"reset_every":0x800000,
"power_cycle":true,
"mbc":0x201,
"write_pin":"WR",
"command_set":"AMD",
"commands":{
"reset":[
[ 0, 0xF0 ]
],
"read_identifier":[
[ 0xAAA, 0xA9 ],
[ 0x555, 0x56 ],
[ 0xAAA, 0x90 ]
],
"read_cfi":[
[ 0xAA, 0x98 ]
],
"chip_erase":[
[ 0xAAA, 0xA9 ],
[ 0x555, 0x56 ],
[ 0xAAA, 0x80 ],
[ 0xAAA, 0xA9 ],
[ 0x555, 0x56 ],
[ 0xAAA, 0x10 ]
],
"chip_erase_wait_for":[
[ null, null, null ],
[ null, null, null ],
[ null, null, null ],
[ null, null, null ],
[ null, null, null ],
[ 0, 0xFF, 0xFF ]
],
"sector_erase":[
[ 0xAAA, 0xA9 ],
[ 0x555, 0x56 ],
[ 0xAAA, 0x80 ],
[ 0xAAA, 0xA9 ],
[ 0x555, 0x56 ],
[ "SA", 0x30 ]
],
"sector_erase_wait_for":[
[ null, null, null ],
[ null, null, null ],
[ null, null, null ],
[ null, null, null ],
[ null, null, null ],
[ "SA", 0xFF, 0xFF ]
],
"single_write":[
[ 0xAAA, 0xA9 ],
[ 0x555, 0x56 ],
[ 0xAAA, 0xA0 ],
[ "PA", "PD" ]
],
"single_write_wait_for":[
[ null, null, null ],
[ null, null, null ],
[ null, null, null ],
[ null, null, null ]
]
}
}

View File

@ -0,0 +1,54 @@
{
"type":"DMG",
"names":[
"Ferrante Crafts cart 32 KB V2"
],
"flash_ids":[
[ 0xBF, 0xFF, 0x25, 0xFF ]
],
"voltage":5,
"flash_size":0x8000,
"start_addr":0,
"first_bank":1,
"write_pin":"WR",
"chip_erase_timeout":20,
"command_set":"AMD",
"commands":{
"reset":[
[ 0, 0xF0 ]
],
"read_identifier":[
[ 0x5555, 0xAA ],
[ 0x2AAA, 0x55 ],
[ 0x5555, 0x90 ]
],
"chip_erase":[
[ 0x5555, 0xAA ],
[ 0x2AAA, 0x55 ],
[ 0x5555, 0x80 ],
[ 0x5555, 0xAA ],
[ 0x2AAA, 0x55 ],
[ 0x5555, 0x10 ]
],
"chip_erase_wait_for":[
[ null, null, null ],
[ null, null, null ],
[ null, null, null ],
[ null, null, null ],
[ null, null, null ],
[ 0, 0xFF, 0xFF ]
],
"single_write":[
[ 0x5555, 0xAA ],
[ 0x2AAA, 0x55 ],
[ 0x5555, 0xA0 ],
[ "PA", "PD" ]
],
"single_write_wait_for":[
[ null, null, null ],
[ null, null, null ],
[ null, null, null ],
[ null, null, null ]
]
}
}

View File

@ -0,0 +1,54 @@
{
"type":"DMG",
"names":[
"insideGadgets 4 MB (MX29LV320ET)"
],
"flash_ids":[
[ 0xC2, 0xC2, 0xA7, 0xA7 ]
],
"voltage":5,
"flash_size":0x400000,
"start_addr":0,
"first_bank":1,
"write_pin":"WR",
"chip_erase_timeout":60,
"command_set":"AMD",
"commands":{
"reset":[
[ 0, 0xF0 ]
],
"read_identifier":[
[ 0xAAA, 0xAA ],
[ 0x555, 0x55 ],
[ 0xAAA, 0x90 ]
],
"chip_erase":[
[ 0xAAA, 0xAA ],
[ 0x555, 0x55 ],
[ 0xAAA, 0x80 ],
[ 0xAAA, 0xAA ],
[ 0x555, 0x55 ],
[ 0xAAA, 0x10 ]
],
"chip_erase_wait_for":[
[ null, null, null ],
[ null, null, null ],
[ null, null, null ],
[ null, null, null ],
[ null, null, null ],
[ 0, 0xFF, 0xFF ]
],
"single_write":[
[ 0xAAA, 0xAA ],
[ 0x555, 0x55 ],
[ 0xAAA, 0xA0 ],
[ "PA", "PD" ]
],
"single_write_wait_for":[
[ null, null, null ],
[ null, null, null ],
[ null, null, null ],
[ null, null, null ]
]
}
}

View File

@ -17,7 +17,7 @@ class GbxDevice:
DEVICE_NAME = "GBxCart RW"
DEVICE_MIN_FW = 1
DEVICE_MAX_FW = 7
DEVICE_LATEST_FW_TS = { 4:1619427330, 5:1653902765, 6:1653902765 }
DEVICE_LATEST_FW_TS = { 4:1619427330, 5:1657187182, 6:1657187182 }
DEVICE_CMD = {
"NULL":0x30,
@ -142,7 +142,7 @@ class GbxDevice:
dev.close()
self.DEVICE = None
self.BAUDRATE = 1000000
return False
continue
elif max_baud >= 1700000 and self.FW["pcb_ver"] in (5, 6, 101) and self.BAUDRATE < 1700000:
# Switch to higher baud rate
self._write(self.DEVICE_CMD["OFW_USART_1_7M_SPEED"])
@ -163,7 +163,7 @@ class GbxDevice:
elif self.FW is None or "cfw_id" not in self.FW or self.FW["cfw_id"] != 'L': # Not a CFW by Lesserkuma
dev.close()
self.DEVICE = None
return False
continue
elif self.FW["fw_ver"] < self.DEVICE_MIN_FW:
dev.close()
self.DEVICE = None
@ -177,7 +177,7 @@ class GbxDevice:
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
return False
continue
conn_msg.append([0, "For help please visit the insideGadgets Discord: https://gbxcart.com/discord"])

Binary file not shown.

Binary file not shown.

Binary file not shown.

View File

@ -144,6 +144,7 @@ Use this command in a Terminal or Command Prompt window to launch the installed
- Game Boy
- 2006_TSOP_64BALL_QFP48 with AL016J55FFAR2
- 256M29EWH (no PCB text)
- 36VF3204 and ALTERA CPLD (no PCB text)
- DMG-DHCN-20 with MX29LV320ET
- DMG-GBRW-20 with 29LV320ETMI-70G
@ -290,7 +291,9 @@ The author would like to thank the following very kind people for their help and
- crizzlycruz (flash chip info)
- Davidish (flash chip info)
- DevDavisNunez (bug reports)
- Diddy_Kong (sample cartridge contribution)
- djedditt (testing)
- Dr-InSide (bug reports)
- dyf2007 (flash chip info)
- easthighNerd (feature suggestions)
- EchelonPrime (flash chip info)
@ -342,11 +345,13 @@ The author would like to thank the following very kind people for their help and
- t5b6_de (flash chip info)
- Timville (sample cartridge contribution, flash chip info)
- twitnic (flash chip info)
- velipso (bug reports)
- Veund (flash chip info)
- voltagex (bug reports)
- Voultar (bug reports, feature suggestions)
- Wkr (flash chip info)
- x7l7j8cc (flash chip info)
- xactoes (testing)
- Zeii (flash chip info)
- Zelante (flash chip info)
- zvxr (flash chip info)

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.15",
version="3.16",
author="Lesserkuma",
description="Reads and writes Game Boy and Game Boy Advance cartridge data. Supported hardware: GBxCart RW v1.3 and v1.4 by insideGadgets.",
url="https://github.com/lesserkuma/FlashGBX",