Skip to content

Commit

Permalink
3.37
Browse files Browse the repository at this point in the history
  • Loading branch information
lesserkuma committed Mar 1, 2024
1 parent 76533a9 commit 8ba45ad
Show file tree
Hide file tree
Showing 23 changed files with 506 additions and 80 deletions.
7 changes: 7 additions & 0 deletions CHANGES.md
Original file line number Diff line number Diff line change
@@ -1,4 +1,11 @@
# Release notes
### v3.37 (released 2024-03-01)
- Bundles GBxCart RW v1.4/v1.4a firmware version R42+L11 (improves flash cart compatibility)
- Added support for F0095_4G_V1 with F0095H0 *(thanks Ausar)*
- Improved support for 256M29EWH (no PCB text)
- Confirmed and improved support for 512M29EWH (no PCB text)
- Minor bug fixes and improvements

### v3.36 (released 2024-01-15)
- Added support for DIY cart with 28F016S5 *(thanks alexbc2999)*
- Fixed a problem with reading Sachen cartridges *(thanks xukkorz)*
Expand Down
2 changes: 1 addition & 1 deletion FlashGBX/FlashGBX.py
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,7 @@ def main(portableMode=False):
ap_cli2.add_argument("--dmg-romsize", choices=["auto", "32kb", "64kb", "128kb", "256kb", "512kb", "1mb", "2mb", "4mb", "8mb", "16mb", "32mb"], type=str.lower, default="auto", help="set size of Game Boy cartridge ROM data")
ap_cli2.add_argument("--dmg-mbc", type=str.lower, default="auto", help="set memory bank controller type of Game Boy cartridge")
ap_cli2.add_argument("--dmg-savesize", choices=["auto", "4k", "16k", "64k", "256k", "512k", "1m", "eeprom2k", "eeprom4k", "tama5", "4m"], type=str.lower, default="auto", help="set size of Game Boy cartridge save data")
ap_cli2.add_argument("--agb-romsize", choices=["auto", "64kb", "128kb", "256kb", "512kb", "1mb", "2mb", "4mb", "8mb", "16mb", "32mb", "64mb", "128mb", "256mb"], type=str.lower, default="auto", help="set size of Game Boy Advance cartridge ROM data")
ap_cli2.add_argument("--agb-romsize", choices=["auto", "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", help="store RTC register values if supported")
ap_cli2.add_argument("--ignore-bad-header", action="store_true", help="don’t stop if invalid data found in cartridge header data")
Expand Down
13 changes: 8 additions & 5 deletions FlashGBX/FlashGBX_CLI.py
Original file line number Diff line number Diff line change
Expand Up @@ -593,7 +593,7 @@ def DetectCartridge(self, limitVoltage=False):
header = self.CONN.ReadInfo()
self.ReadCartridge(header)
ret = self.CONN.DetectCartridge(limitVoltage=limitVoltage, checkSaveType=True)
(header, _, save_type, save_chip, sram_unstable, cart_types, cart_type_id, cfi_s, _, flash_id) = ret
(header, _, save_type, save_chip, sram_unstable, cart_types, cart_type_id, cfi_s, _, flash_id, detected_size) = ret

# Save Type
if save_type is None:
Expand Down Expand Up @@ -645,7 +645,10 @@ def DetectCartridge(self, limitVoltage=False):
(flash_id, cfi_s, _) = self.CONN.CheckFlashChip(limitVoltage=limitVoltage, cart_type=supp_cart_types[1][cart_type])
msg_cart_type_s = "Cartridge Type: Supported flash cartridge – compatible with:\n{:s}\n".format(msg_cart_type)

if "flash_size" in supp_cart_types[1][cart_type_id]:
if detected_size > 0:
size = detected_size
msg_flash_size_s = "ROM Size: {:s}\n".format(Util.formatFileSize(size=size, asInt=True))
elif "flash_size" in supp_cart_types[1][cart_type_id]:
size = supp_cart_types[1][cart_type_id]["flash_size"]
msg_flash_size_s = "ROM Size: {:s}\n".format(Util.formatFileSize(size=size, asInt=True))

Expand Down Expand Up @@ -741,7 +744,7 @@ def BackupROM(self, args, header):
if args.agb_romsize == "auto":
rom_size = header["rom_size"]
else:
sizes = [ "auto", "64kb", "128kb", "256kb", "512kb", "1mb", "2mb", "4mb", "8mb", "16mb", "32mb", "64mb", "128mb", "256mb" ]
sizes = [ "auto", "64kb", "128kb", "256kb", "512kb", "1mb", "2mb", "4mb", "8mb", "16mb", "32mb", "64mb", "128mb", "256mb", "512mb" ]
rom_size = Util.AGB_Header_ROM_Sizes_Map[sizes.index(args.agb_romsize) - 1]

if args.path != "auto":
Expand Down Expand Up @@ -855,8 +858,8 @@ def FlashROM(self, args, header):
path = args.path

try:
if os.path.getsize(path) > 0x10000000: # reject too large files to avoid exploding RAM
print("{:s}ROM files bigger than 256 MiB are not supported.{:s}".format(ANSI.RED, ANSI.RESET))
if os.path.getsize(path) > 0x20000000: # reject too large files to avoid exploding RAM
print("{:s}ROM files bigger than 512 MiB are not supported.{:s}".format(ANSI.RED, ANSI.RESET))
return
elif os.path.getsize(path) < 0x400:
print("{:s}ROM files smaller than 1 KiB are not supported.{:s}".format(ANSI.RED, ANSI.RESET))
Expand Down
13 changes: 8 additions & 5 deletions FlashGBX/FlashGBX_GUI.py
Original file line number Diff line number Diff line change
Expand Up @@ -690,7 +690,7 @@ def ConnectDevice(self):
dev.SetWriteDelay(enable=str(self.SETTINGS.value("WriteDelay", default="disabled")).lower() == "enabled")
qt_app.processEvents()
self.CONN = dev
self.CONN.SetTimeout(float(self.SETTINGS.value("SerialTimeout", default="0.5")))
self.CONN.SetTimeout(float(self.SETTINGS.value("SerialTimeout", default="1")))
self.optDMG.setAutoExclusive(False)
self.optAGB.setAutoExclusive(False)
if "DMG" in self.CONN.GetSupprtedModes():
Expand Down Expand Up @@ -1258,8 +1258,8 @@ def FlashROM(self, dpath=""):
if os.path.getsize(path) == 0:
QtWidgets.QMessageBox.critical(self, "{:s} {:s}".format(APPNAME, VERSION), "The selected ROM file is empty.", QtWidgets.QMessageBox.Ok)
return
if os.path.getsize(path) > 0x10000000: # reject too large files to avoid exploding RAM
QtWidgets.QMessageBox.critical(self, "{:s} {:s}".format(APPNAME, VERSION), "ROM files bigger than 256 MiB are not supported.", QtWidgets.QMessageBox.Ok)
if os.path.getsize(path) > 0x20000000: # reject too large files to avoid exploding RAM
QtWidgets.QMessageBox.critical(self, "{:s} {:s}".format(APPNAME, VERSION), "ROM files bigger than 512 MiB are not supported.", QtWidgets.QMessageBox.Ok)
return

with open(path, "rb") as file:
Expand Down Expand Up @@ -2339,7 +2339,7 @@ def DetectCartridge(self, canSkipMessage=False):
self.DisconnectDevice()
cart_type = None
else:
(header, save_size, save_type, save_chip, sram_unstable, cart_types, cart_type_id, cfi_s, _, flash_id) = ret
(header, save_size, save_type, save_chip, sram_unstable, cart_types, cart_type_id, cfi_s, _, flash_id, detected_size) = ret

# Save Type
if not canSkipMessage:
Expand Down Expand Up @@ -2436,7 +2436,10 @@ def DetectCartridge(self, canSkipMessage=False):
msg_cart_type_s_detail = "<b>Compatible Cartridge Types:</b><br>{:s}<br>".format(msg_cart_type)
found_supported = True

if "flash_size" in supp_cart_types[1][cart_type_id]:
if detected_size > 0:
size = detected_size
msg_flash_size_s = "<b>ROM Size:</b> {:s}<br>".format(Util.formatFileSize(size=size, asInt=True))
elif "flash_size" in supp_cart_types[1][cart_type_id]:
size = supp_cart_types[1][cart_type_id]["flash_size"]
msg_flash_size_s = "<b>ROM Size:</b> {:s}<br>".format(Util.formatFileSize(size=size, asInt=True))

Expand Down
12 changes: 11 additions & 1 deletion FlashGBX/Flashcart.py
Original file line number Diff line number Diff line change
Expand Up @@ -133,6 +133,10 @@ def GetFlashSize(self, default=False):
if "flash_size" not in self.CONFIG: return default
return self.CONFIG["flash_size"]

def SetFlashSize(self, size):
if "flash_size" not in self.CONFIG: return
self.CONFIG["flash_size"] = size

def GetBufferSize(self):
if "buffer_size" in self.CONFIG:
return self.CONFIG["buffer_size"]
Expand Down Expand Up @@ -450,11 +454,17 @@ def SectorErase(self, pos=0, buffer_pos=0):
else:
return self.CONFIG["sector_size"]

def HasBanks(self):
return "flash_bank_select_type" in self.CONFIG

def SelectBankROM(self, index):
if "flash_bank_select_type" not in self.CONFIG: return False
dprint(f"Setting flash bank to {index:d}")
if self.CONFIG["flash_bank_select_type"] == 1:
dprint(self.GetName(), "|", index)
index = index & 0xF
self.CartWrite([[2, index << 4]], sram=True)
self.CartWrite([[3, 0x40]], sram=True)
self.CartWrite([[4, 0x00]], sram=True)
return True
elif self.CONFIG["flash_bank_select_type"] == 2: # Flash2Advance Ultra
bank1 = 0 if index < 4 else 0x10
Expand Down
55 changes: 26 additions & 29 deletions FlashGBX/Util.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,19 +7,19 @@

# Common constants
APPNAME = "FlashGBX"
VERSION_PEP440 = "3.36"
VERSION_PEP440 = "3.37"
VERSION = "v{:s}".format(VERSION_PEP440)
VERSION_TIMESTAMP = 1705328830
VERSION_TIMESTAMP = 1709318129
DEBUG = False
DEBUG_LOG = []
APP_PATH = ""
CONFIG_PATH = ""

AGB_Header_ROM_Sizes = [ "64 KiB", "128 KiB", "256 KiB", "512 KiB", "1 MiB", "2 MiB", "4 MiB", "8 MiB", "16 MiB", "32 MiB", "64 MiB", "128 MiB", "256 MiB" ]
AGB_Header_ROM_Sizes_Map = [ 0x10000, 0x20000, 0x40000, 0x80000, 0x100000, 0x200000, 0x400000, 0x800000, 0x1000000, 0x2000000, 0x4000000, 0x8000000, 0x10000000 ]
AGB_Header_ROM_Sizes = [ "64 KiB", "128 KiB", "256 KiB", "512 KiB", "1 MiB", "2 MiB", "4 MiB", "8 MiB", "16 MiB", "32 MiB", "64 MiB", "128 MiB", "256 MiB", "512 MiB" ]
AGB_Header_ROM_Sizes_Map = [ 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 SST SST49LF080A", 0xFFFF:"Unlicensed 0xFFFF" }
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 ]

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' }
Expand Down Expand Up @@ -314,30 +314,27 @@ def formatProgressTimeShort(sec):
sec %= 60
return "{:02d}:{:02d}:{:02d}".format(int(hr), int(min), int(sec))

def formatProgressTime(sec, asFloat=False):
if int(sec) == 1:
return "{:d} second".format(int(sec))
elif sec < 60:
if sec < 1 and asFloat:
return "{:.2f} seconds".format(sec)
else:
return "{:d} seconds".format(int(sec))
elif int(sec) == 60:
return "1 minute"
else:
min = int(sec / 60)
sec = int(sec % 60)
s = str(min) + " "
if min == 1:
s = s + "minute"
else:
s = s + "minutes"
s = s + ", " + str(sec) + " "
if sec == 1:
s = s + "second"
else:
s = s + "seconds"
return s
def formatProgressTime(seconds, asFloat=False):
hr = int(seconds // 3600)
min = int((seconds // 60) - (60 * hr))
sec = seconds % 60

if seconds < 1 and asFloat:
return "{:.2f} seconds".format(seconds)
s = ""
if hr > 0:
s += "{:d} hour".format(hr)
if hr != 1: s += "s"
s += ", "
if min > 0:
s += "{:d} minute".format(min)
if min != 1: s += "s"
s += ", "
if sec >= 1 or seconds < 60:
s += "{:d} second".format(int(sec))
if sec != 1: s += "s"
s += ", "
return s[:-2]

def formatPathOS(path, end_sep=False):
if platform.system() == "Windows":
Expand Down
8 changes: 4 additions & 4 deletions FlashGBX/config/db_AGB.json
Original file line number Diff line number Diff line change
Expand Up @@ -489,8 +489,8 @@
"gc": "A2YE",
"rc": 3754462526,
"rs": 4194304,
"st": 4,
"ss": 65536,
"st": 0,
"ss": 0,
"lg": "En,Fr,De,Es,It",
"rg": "USA"
},
Expand Down Expand Up @@ -21226,11 +21226,11 @@
"lg": "Ja",
"rg": "Japan"
},
"f71e3df4bf5f4c9000b9e3c931696bf237e6cac6": {
"414992293e84502d31cbc612234fbb15427e9a81": {
"gn": "Fear Factor - Unleashed",
"ne": "(USA)",
"gc": "BFUE",
"rc": 310993820,
"rc": 3214000765,
"rs": 8388608,
"st": 1,
"ss": 512,
Expand Down
9 changes: 9 additions & 0 deletions FlashGBX/config/db_DMG.json
Original file line number Diff line number Diff line change
Expand Up @@ -207,6 +207,15 @@
"lg": "En,Fr,De,Es,It",
"rg": "Europe"
},
"70d6c1b7b0dab7f6dec9dbc4eae454a19a37d6cd": {
"gn": "Trip World DX",
"ne": "(USA) (Limited Run Games)",
"gc": "",
"rc": 2937566187,
"rs": 524288,
"lg": "En",
"rg": "USA"
},
"bdf78e28adb73b3bec1c232bb5102cd9cb6128c5": {
"gn": "Tutty",
"ne": "(Europe) (Demo)",
Expand Down
52 changes: 52 additions & 0 deletions FlashGBX/config/fc_AGB_F0095H0.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
{
"type":"AGB",
"names":[
"F0095_4G_V1 with F0095H0"
],
"flash_ids":[
[ 0x8A, 0x00, 0xB0, 0x88 ]
],
"voltage":3.3,
"flash_size":0x20000000,
"flash_bank_size":0x2000000,
"flash_bank_select_type":1,
"sector_size":0x40000,
"reset_every":0x400000,
"buffer_size":1024,
"command_set":"INTEL",
"commands":{
"reset":[
[ 0, 0x50 ],
[ 0, 0xFF ]
],
"read_identifier":[
[ 0, 0x90 ]
],
"sector_erase":[
[ "SA", 0x60 ],
[ "SA", 0xD0 ],
[ "SA", 0x20 ],
[ "SA", 0xD0 ]
],
"sector_erase_wait_for":[
[ null, null, null ],
[ null, null, null ],
[ null, null, null ],
[ "SA", 0x80, 0x80 ]
],
"buffer_write":[
[ "SA", 0xEA ],
[ "SA", "BS" ],
[ "PA", "PD" ],
[ "SA", 0xD0 ],
[ "SA", 0xFF ]
],
"buffer_write_wait_for":[
[ "SA", 0x80, 0x80 ],
[ null, null, null ],
[ null, null, null ],
[ "SA", 0x80, 0x80 ],
[ null, null, null ]
]
}
}
23 changes: 21 additions & 2 deletions FlashGBX/config/fc_DMG_256M29EWH.txt
Original file line number Diff line number Diff line change
@@ -1,9 +1,11 @@
{
"type":"DMG",
"names":[
"256M29EWH (no PCB text)"
"256M29EWH (no PCB text)",
"512M29EWH (no PCB text)"
],
"flash_ids":[
[ 0x8A, 0x8A, 0x7D, 0x7D ],
[ 0x8A, 0x8A, 0x7D, 0x7D ]
],
"voltage":3.3,
Expand All @@ -13,6 +15,7 @@
"first_bank":1,
"chip_erase_timeout":120,
"sector_size_from_cfi":true,
"buffer_size":256,
"reset_every":0x800000,
"mbc":0x201,
"write_pin":"WR",
Expand Down Expand Up @@ -59,7 +62,23 @@
[ null, null, null ],
[ null, null, null ],
[ null, null, null ],
[ "SA", 0xFF, 0xFF ]
[ "SA", 0x80, 0x80 ]
],
"buffer_write":[
[ 0xAAA, 0xA9 ],
[ 0x555, 0x56 ],
[ "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", 0xFF ]
],
"single_write":[
[ 0xAAA, 0xA9 ],
Expand Down
43 changes: 43 additions & 0 deletions FlashGBX/config/fc_DMG_28F016S5.txt
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
{
"type":"DMG",
"names":[
"DIY cart with 28F016S5 @ AUDIO"
],
"flash_ids":[
[ 0x89, 0xAA ]
],
"voltage":5,
"flash_size":0x200000,
"sector_size":0x10000,
"start_addr":0,
"first_bank":1,
"write_pin":"AUDIO",
"mbc":"manual",
"command_set":"INTEL",
"commands":{
"reset":[
[ 0, 0xFF ]
],
"read_identifier":[
[ 0, 0x90 ]
],
"sector_erase":[
[ 0x4000, 0x20 ],
[ 0x4000, 0xD0 ]
],
"sector_erase_wait_for":[
[ null, null, null ],
[ 0x4000, 0x80, 0x80 ]
],
"single_write":[
[ "PA", 0x70 ],
[ "PA", 0x40 ],
[ "PA", "PD" ]
],
"single_write_wait_for":[
[ 0, 0x80, 0x80 ],
[ null, null, null ],
[ null, null, null ]
]
}
}
Loading

0 comments on commit 8ba45ad

Please sign in to comment.