FlashGBX 4.3__py3-none-any.whl → 4.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- FlashGBX/FlashGBX.py +1 -1
- FlashGBX/FlashGBX_CLI.py +24 -17
- FlashGBX/FlashGBX_GUI.py +346 -139
- FlashGBX/Flashcart.py +2 -1
- FlashGBX/GBMemory.py +3 -1
- FlashGBX/LK_Device.py +301 -216
- FlashGBX/Mapper.py +4 -4
- FlashGBX/PocketCameraWindow.py +31 -1
- FlashGBX/RomFileAGB.py +4 -1
- FlashGBX/RomFileDMG.py +7 -2
- FlashGBX/Util.py +30 -8
- FlashGBX/fw_JoeyJr.py +8 -1
- FlashGBX/hw_GBFlash.py +2 -2
- FlashGBX/hw_GBxCartRW.py +15 -15
- FlashGBX/hw_JoeyJr.py +2 -2
- FlashGBX/res/config.zip +0 -0
- FlashGBX/res/fw_GBFlash.zip +0 -0
- FlashGBX/res/fw_GBxCart_RW_v1_4.zip +0 -0
- FlashGBX/res/fw_GBxCart_RW_v1_4a.zip +0 -0
- FlashGBX/res/fw_JoeyJr.zip +0 -0
- {FlashGBX-4.3.dist-info → FlashGBX-4.4.dist-info}/METADATA +91 -52
- FlashGBX-4.4.dist-info/RECORD +43 -0
- {FlashGBX-4.3.dist-info → FlashGBX-4.4.dist-info}/WHEEL +1 -1
- FlashGBX-4.3.dist-info/RECORD +0 -43
- {FlashGBX-4.3.dist-info → FlashGBX-4.4.dist-info}/LICENSE +0 -0
- {FlashGBX-4.3.dist-info → FlashGBX-4.4.dist-info}/entry_points.txt +0 -0
- {FlashGBX-4.3.dist-info → FlashGBX-4.4.dist-info}/top_level.txt +0 -0
FlashGBX/LK_Device.py
CHANGED
|
@@ -31,7 +31,7 @@ class LK_Device(ABC):
|
|
|
31
31
|
"OFW_FW_VER":0x56,
|
|
32
32
|
"OFW_PCB_VER":0x68,
|
|
33
33
|
"OFW_USART_1_0M_SPEED":0x3C,
|
|
34
|
-
"
|
|
34
|
+
"OFW_USART_1_5M_SPEED":0x3E,
|
|
35
35
|
"OFW_CART_PWR_ON":0x2F,
|
|
36
36
|
"OFW_CART_PWR_OFF":0x2E,
|
|
37
37
|
"OFW_QUERY_CART_PWR":0x5D,
|
|
@@ -114,6 +114,7 @@ class LK_Device(ABC):
|
|
|
114
114
|
"PULLUPS_ENABLED":[8, 0x0E],
|
|
115
115
|
"AUTO_POWEROFF_ENABLED":[8, 0x0F],
|
|
116
116
|
"AGB_IRQ_ENABLED":[8, 0x10],
|
|
117
|
+
"DMG_AUDIO_ENABLED":[8, 0x11],
|
|
117
118
|
}
|
|
118
119
|
|
|
119
120
|
ACTIONS = {"ROM_READ":1, "SAVE_READ":2, "SAVE_WRITE":3, "ROM_WRITE":4, "ROM_WRITE_VERIFY":4, "SAVE_WRITE_VERIFY":3, "RTC_WRITE":5, "DETECT_CART":6}
|
|
@@ -305,7 +306,7 @@ class LK_Device(ABC):
|
|
|
305
306
|
for mode in flashcarts.keys():
|
|
306
307
|
for key in sorted(flashcarts[mode].keys(), key=str.casefold):
|
|
307
308
|
self.SUPPORTED_CARTS[mode][key] = flashcarts[mode][key]
|
|
308
|
-
|
|
309
|
+
|
|
309
310
|
def IsConnected(self):
|
|
310
311
|
if self.DEVICE is None: return False
|
|
311
312
|
if not self.DEVICE.isOpen(): return False
|
|
@@ -679,6 +680,12 @@ class LK_Device(ABC):
|
|
|
679
680
|
self.CartPowerCycle(delay=delay)
|
|
680
681
|
return
|
|
681
682
|
|
|
683
|
+
if self.FW["fw_ver"] < 12:
|
|
684
|
+
self.CANCEL_ARGS.update({"info_type":"msgbox_critical", "info_msg":"This cartridge type requires at least firmware version L12."})
|
|
685
|
+
self.CANCEL = True
|
|
686
|
+
self.USER_ANSWER = None
|
|
687
|
+
return False
|
|
688
|
+
|
|
682
689
|
mode = self.GetMode()
|
|
683
690
|
var_state = self.GetVarState()
|
|
684
691
|
|
|
@@ -836,6 +843,7 @@ class LK_Device(ABC):
|
|
|
836
843
|
self._write(self.DEVICE_CMD["SET_VOLTAGE_5V"], wait=self.FW["fw_ver"] >= 12)
|
|
837
844
|
self._set_fw_variable("DMG_READ_METHOD", self.DMG_READ_METHOD)
|
|
838
845
|
self._set_fw_variable("CART_MODE", 1)
|
|
846
|
+
#if self.FW["fw_ver"] >= 14: self._set_fw_variable("DMG_AUDIO_ENABLED", 0)
|
|
839
847
|
self.MODE = "DMG"
|
|
840
848
|
elif mode == "AGB":
|
|
841
849
|
self._write(self.DEVICE_CMD["SET_MODE_AGB"], wait=self.FW["fw_ver"] >= 12)
|
|
@@ -889,13 +897,9 @@ class LK_Device(ABC):
|
|
|
889
897
|
self.SIGNAL = None
|
|
890
898
|
|
|
891
899
|
def Debug(self):
|
|
892
|
-
# for i in range(0, 0x100000):
|
|
893
|
-
# print(hex(i), self._set_fw_variable("ADDRESS", i), end="\r", flush=True)
|
|
894
900
|
return
|
|
895
901
|
|
|
896
902
|
def ReadInfo(self, setPinsAsInputs=False, checkRtc=True):
|
|
897
|
-
self.Debug()
|
|
898
|
-
|
|
899
903
|
if not self.IsConnected(): raise ConnectionError("Couldn’t access the the device.")
|
|
900
904
|
data = {}
|
|
901
905
|
self.SIGNAL = None
|
|
@@ -959,6 +963,7 @@ class LK_Device(ABC):
|
|
|
959
963
|
data["rtc_string"] = _mbc.GetRTCString()
|
|
960
964
|
except:
|
|
961
965
|
data["rtc_string"] = "Invalid data"
|
|
966
|
+
|
|
962
967
|
if _mbc.GetName() == "G-MMC1":
|
|
963
968
|
try:
|
|
964
969
|
temp = bytearray([0] * 0x100000)
|
|
@@ -976,6 +981,21 @@ class LK_Device(ABC):
|
|
|
976
981
|
print(traceback.format_exc())
|
|
977
982
|
print("{:s}An error occured while trying to read the hidden sector data of the NP GB-Memory cartridge.{:s}".format(ANSI.RED, ANSI.RESET))
|
|
978
983
|
|
|
984
|
+
elif _mbc.GetName() == "MAC-GBD":
|
|
985
|
+
dprint("Reading Game Boy Camera calibration data...")
|
|
986
|
+
_mbc.EnableRAM(True)
|
|
987
|
+
_mbc.SelectBankRAM(2)
|
|
988
|
+
temp = self.ReadRAM(address=0xFF2, length=0xE)
|
|
989
|
+
if temp != bytearray(temp[0] * len(temp)):
|
|
990
|
+
data["gbcamera_calibration1"] = temp
|
|
991
|
+
dprint("Game Boy Camera calibration data 1:", ''.join(format(x, '02X') for x in temp))
|
|
992
|
+
_mbc.SelectBankRAM(8)
|
|
993
|
+
temp = self.ReadRAM(address=0x1FF2, length=0xE)
|
|
994
|
+
if temp != bytearray(temp[0] * len(temp)):
|
|
995
|
+
data["gbcamera_calibration2"] = temp
|
|
996
|
+
dprint("Game Boy Camera calibration data 2:", ''.join(format(x, '02X') for x in temp))
|
|
997
|
+
_mbc.EnableRAM(False)
|
|
998
|
+
|
|
979
999
|
elif self.MODE == "AGB":
|
|
980
1000
|
# Unlock DACS carts on older firmware
|
|
981
1001
|
if not self.CanPowerCycleCart() or self.FW["fw_ver"] == 1:
|
|
@@ -1084,6 +1104,7 @@ class LK_Device(ABC):
|
|
|
1084
1104
|
if self.MODE == "DMG": #and setPinsAsInputs:
|
|
1085
1105
|
self._write(self.DEVICE_CMD["SET_ADDR_AS_INPUTS"], wait=self.FW["fw_ver"] >= 12)
|
|
1086
1106
|
|
|
1107
|
+
self.Debug()
|
|
1087
1108
|
return data
|
|
1088
1109
|
|
|
1089
1110
|
def _DetectCartridge(self, args): # Wrapper for thread call
|
|
@@ -1119,9 +1140,9 @@ class LK_Device(ABC):
|
|
|
1119
1140
|
|
|
1120
1141
|
# Disable Auto Power Off
|
|
1121
1142
|
_apoe = False
|
|
1122
|
-
if self.
|
|
1123
|
-
self.
|
|
1124
|
-
|
|
1143
|
+
if self.FW["fw_ver"] >= 12:
|
|
1144
|
+
if self.CanPowerCycleCart():
|
|
1145
|
+
self.CartPowerCycle()
|
|
1125
1146
|
_apoe = self._get_fw_variable("AUTO_POWEROFF_ENABLED") == 1
|
|
1126
1147
|
if _apoe is True:
|
|
1127
1148
|
_apot = self._get_fw_variable("AUTO_POWEROFF_TIME")
|
|
@@ -1135,8 +1156,11 @@ class LK_Device(ABC):
|
|
|
1135
1156
|
supported_carts = list(self.SUPPORTED_CARTS[self.MODE].values())
|
|
1136
1157
|
cart_type = supported_carts[cart_type_id]
|
|
1137
1158
|
|
|
1159
|
+
# Skip DMG save type detection
|
|
1160
|
+
if self.MODE == "DMG" and cart_type_id == 0: checkSaveType = False
|
|
1161
|
+
|
|
1138
1162
|
# Preparations
|
|
1139
|
-
if "command_set" in cart_type and cart_type["command_set"] in ("DMG-MBC5-32M-FLASH", "GBAMP"):
|
|
1163
|
+
if ("command_set" in cart_type and cart_type["command_set"] in ("DMG-MBC5-32M-FLASH", "GBAMP")) or ("dmg-mbc5-32m-flash" in cart_type):
|
|
1140
1164
|
checkSaveType = False
|
|
1141
1165
|
elif self.MODE == "AGB" and "flash_bank_select_type" in cart_type and cart_type["flash_bank_select_type"] == 1:
|
|
1142
1166
|
save_size = 65536
|
|
@@ -1243,7 +1267,9 @@ class LK_Device(ABC):
|
|
|
1243
1267
|
save_chip = Util.AGB_Flash_Save_Chips[flash_save_id]
|
|
1244
1268
|
|
|
1245
1269
|
if flash_save_id in (0xBF5B, 0xFFFF): # Bootlegs
|
|
1246
|
-
if self.INFO["data"][0:
|
|
1270
|
+
if self.INFO["data"][0:0x20000] == bytearray([0xFF] * 0x20000):
|
|
1271
|
+
save_type = 5
|
|
1272
|
+
elif self.INFO["data"][0:0x10000] == self.INFO["data"][0x10000:0x20000]:
|
|
1247
1273
|
save_type = 4
|
|
1248
1274
|
else:
|
|
1249
1275
|
save_type = 5
|
|
@@ -1253,7 +1279,7 @@ class LK_Device(ABC):
|
|
|
1253
1279
|
save_type = 4
|
|
1254
1280
|
except:
|
|
1255
1281
|
pass
|
|
1256
|
-
|
|
1282
|
+
|
|
1257
1283
|
if save_type is None:
|
|
1258
1284
|
checkBatterylessSRAM = True
|
|
1259
1285
|
if info["dacs_8m"] is True:
|
|
@@ -1284,8 +1310,8 @@ class LK_Device(ABC):
|
|
|
1284
1310
|
save_size = Util.find_size(self.INFO["data"], len(self.INFO["data"]))
|
|
1285
1311
|
eeprom_64k = self.INFO["data"]
|
|
1286
1312
|
if eeprom_64k in (bytearray([0xFF] * len(eeprom_64k)), bytearray([0] * len(eeprom_64k))):
|
|
1287
|
-
save_type = None
|
|
1288
1313
|
save_size = 0
|
|
1314
|
+
save_type = 0
|
|
1289
1315
|
elif (eeprom_4k == eeprom_64k[:len(eeprom_4k)]):
|
|
1290
1316
|
save_type = 2
|
|
1291
1317
|
save_size = 8192
|
|
@@ -1378,6 +1404,7 @@ class LK_Device(ABC):
|
|
|
1378
1404
|
|
|
1379
1405
|
def ReadFlashSaveID(self):
|
|
1380
1406
|
# Check if actually SRAM/FRAM
|
|
1407
|
+
dprint("Checking Flash ID of Save Memory")
|
|
1381
1408
|
test1 = self._cart_read(0, 0x10, agb_save_flash=True)[4]
|
|
1382
1409
|
self._cart_write_flash([[ 0x0004, test1 ^ 0xFF ]])
|
|
1383
1410
|
test2 = self._cart_read(0, 0x10, agb_save_flash=True)[4]
|
|
@@ -1735,7 +1762,6 @@ class LK_Device(ABC):
|
|
|
1735
1762
|
self._set_fw_variable("ADDRESS", address)
|
|
1736
1763
|
elif self.MODE == "AGB":
|
|
1737
1764
|
self._set_fw_variable("ADDRESS", address >> 1)
|
|
1738
|
-
# print("==>", hex(self._get_fw_variable("ADDRESS")), hex(self._get_fw_variable("TRANSFER_SIZE")), hex(self._get_fw_variable("BUFFER_SIZE")))
|
|
1739
1765
|
|
|
1740
1766
|
skip_init = True
|
|
1741
1767
|
|
|
@@ -1839,9 +1865,6 @@ class LK_Device(ABC):
|
|
|
1839
1865
|
self._write(buffer[i*length:i*length+length])
|
|
1840
1866
|
ret = self._read(1)
|
|
1841
1867
|
if ret not in (0x01, 0x03):
|
|
1842
|
-
#self.CANCEL_ARGS.update({"info_type":"msgbox_critical", "info_msg":"Flash write error (response = {:s}) in iteration {:d} while trying to write 0x{:X} bytes".format(str(ret), i, length)})
|
|
1843
|
-
#self.CANCEL = True
|
|
1844
|
-
#self.ERROR = True
|
|
1845
1868
|
return False
|
|
1846
1869
|
|
|
1847
1870
|
self._cart_write(address + length - 1, 0xFF)
|
|
@@ -1984,7 +2007,7 @@ class LK_Device(ABC):
|
|
|
1984
2007
|
buffer2 = self.ReadROM(0x80, 0x40)
|
|
1985
2008
|
return buffer1 == buffer2
|
|
1986
2009
|
|
|
1987
|
-
def CompareCRC32(self, buffer, offset, length, address, flashcart=None, max_length=0x20000, reset=False):
|
|
2010
|
+
def CompareCRC32(self, buffer, offset, length, address, flashcart=None, max_length=0x20000, reset=False, mbc=None, bank=0):
|
|
1988
2011
|
left = length
|
|
1989
2012
|
chunk_pos = 0
|
|
1990
2013
|
verified = False
|
|
@@ -2010,6 +2033,8 @@ class LK_Device(ABC):
|
|
|
2010
2033
|
if crc32_expected != crc32_calculated:
|
|
2011
2034
|
if i == 0 and flashcart is not None:
|
|
2012
2035
|
flashcart.Reset(full_reset=True)
|
|
2036
|
+
if mbc is not None:
|
|
2037
|
+
mbc.SelectBankROM(bank)
|
|
2013
2038
|
verified = (crc32_expected, crc32_calculated)
|
|
2014
2039
|
continue
|
|
2015
2040
|
else:
|
|
@@ -2065,11 +2090,24 @@ class LK_Device(ABC):
|
|
|
2065
2090
|
cmds = []
|
|
2066
2091
|
cmds_reset = []
|
|
2067
2092
|
cmds_unlock_read = []
|
|
2068
|
-
|
|
2069
|
-
|
|
2093
|
+
|
|
2094
|
+
for cart_type in sorted(supported_carts, key=lambda c: 'm29w640' not in c): # m29w640 first because of corruption risk
|
|
2095
|
+
f = supported_carts.index(cart_type)
|
|
2070
2096
|
if "command_set" not in cart_type: continue
|
|
2071
2097
|
if "manual_select" in cart_type and cart_type["manual_select"] is True: continue
|
|
2072
|
-
if self.MODE == "DMG" and
|
|
2098
|
+
if self.MODE == "DMG" and "m29w640" in cart_type:
|
|
2099
|
+
self._cart_write_flash(cart_type["commands"]["reset"])
|
|
2100
|
+
rom1 = self._cart_read(0, 8)
|
|
2101
|
+
self._cart_write_flash(cart_type["commands"]["read_identifier"])
|
|
2102
|
+
rom2 = self._cart_read(0, 8)
|
|
2103
|
+
if rom1 != rom2 and list(rom2[:len(cart_type["flash_ids"][0])]) == cart_type["flash_ids"][0]:
|
|
2104
|
+
found = True
|
|
2105
|
+
flash_types.append(f)
|
|
2106
|
+
dprint("Found a M29W640 cartridge")
|
|
2107
|
+
self._cart_write_flash(cart_type["commands"]["reset"])
|
|
2108
|
+
break
|
|
2109
|
+
continue
|
|
2110
|
+
elif self.MODE == "DMG" and cart_type["command_set"] == "BLAZE_XPLODER":
|
|
2073
2111
|
self._cart_read(0x102, 1)
|
|
2074
2112
|
self._cart_write(6, 1)
|
|
2075
2113
|
self._cart_write_flash(cart_type["commands"]["reset"])
|
|
@@ -2110,7 +2148,7 @@ class LK_Device(ABC):
|
|
|
2110
2148
|
self._cart_write_flash(cart_type["commands"]["reset"])
|
|
2111
2149
|
break
|
|
2112
2150
|
continue
|
|
2113
|
-
elif self.MODE == "DMG" and
|
|
2151
|
+
elif self.MODE == "DMG" and "dmg-mbc5-32m-flash" in cart_type:
|
|
2114
2152
|
self._set_we_pin_audio()
|
|
2115
2153
|
self._cart_write_flash(cart_type["commands"]["unlock"], flashcart=False)
|
|
2116
2154
|
self._cart_write_flash(cart_type["commands"]["reset"])
|
|
@@ -2200,6 +2238,7 @@ class LK_Device(ABC):
|
|
|
2200
2238
|
self._cart_write(cmd[0], cmd[1], flashcart=True)
|
|
2201
2239
|
|
|
2202
2240
|
flash_id_cmds = sorted(cmds, key=lambda x: x['read_identifier'][0][0])
|
|
2241
|
+
read_cfi_cmds = []
|
|
2203
2242
|
|
|
2204
2243
|
rom_s = " ".join(format(x, '02X') for x in rom)
|
|
2205
2244
|
if self.MODE == "DMG":
|
|
@@ -2225,41 +2264,13 @@ class LK_Device(ABC):
|
|
|
2225
2264
|
cmp = self._cart_read(0, 8)
|
|
2226
2265
|
self._cart_write_flash(flash_id_cmds[i]["reset"], flashcart=True)
|
|
2227
2266
|
if rom != cmp: # ROM data changed
|
|
2228
|
-
if "read_cfi" not in flash_id_cmds[i]:
|
|
2229
|
-
flash_id_cmds[i]["read_cfi"] = [[ flash_id_cmds[i]["read_identifier"][0][0], 0x98 ]]
|
|
2230
|
-
self._cart_write_flash(flash_id_cmds[i]["read_cfi"], flashcart=True)
|
|
2231
|
-
cfi_buffer = self._cart_read(0, 0x400)
|
|
2232
|
-
self._cart_write_flash(flash_id_cmds[i]["reset"], flashcart=True)
|
|
2233
2267
|
flash_id_methods.append([we - 1, i, list(cmp), cfi_buffer, flash_id_cmds[i]["read_identifier"]])
|
|
2234
|
-
|
|
2235
|
-
if ".dev" in Util.VERSION_PEP440 or Util.DEBUG:
|
|
2236
|
-
with open(Util.CONFIG_PATH + "/debug_cfi.bin", "wb") as f: f.write(cfi_buffer)
|
|
2237
|
-
try:
|
|
2238
|
-
magic = "{:s}{:s}{:s}".format(chr(cfi_buffer[0x20]), chr(cfi_buffer[0x22]), chr(cfi_buffer[0x24]))
|
|
2239
|
-
d_swap = (0, 0)
|
|
2240
|
-
if magic == "QRY": # D0D1 not swapped
|
|
2241
|
-
pass
|
|
2242
|
-
elif magic == "RQZ": # D0D1 swapped
|
|
2243
|
-
d_swap = [(0, 1)]
|
|
2244
|
-
for j2 in range(0, len(d_swap)):
|
|
2245
|
-
for j in range(0, len(cfi_buffer)):
|
|
2246
|
-
cfi_buffer[j] = bitswap(cfi_buffer[j], d_swap[j2])
|
|
2247
|
-
elif magic == "\x92\x91\x9A": # D0D1+D6D7 swapped
|
|
2248
|
-
d_swap = [( 0, 1 ), ( 6, 7 )]
|
|
2249
|
-
for j2 in range(0, len(d_swap)):
|
|
2250
|
-
for j in range(0, len(cfi_buffer)):
|
|
2251
|
-
cfi_buffer[j] = bitswap(cfi_buffer[j], d_swap[j2])
|
|
2252
|
-
if ".dev" in Util.VERSION_PEP440 or Util.DEBUG:
|
|
2253
|
-
with open(Util.CONFIG_PATH + "/debug_cfi_d0d1+d6d7.bin", "wb") as f: f.write(cfi_buffer)
|
|
2254
|
-
else:
|
|
2255
|
-
cfi_buffer = None
|
|
2256
|
-
except:
|
|
2257
|
-
cfi_buffer = None
|
|
2258
|
-
|
|
2259
2268
|
if self.MODE == "DMG":
|
|
2260
2269
|
flash_id_s += "[{:s}/{:4X}/{:2X}] {:s}\n".format(we_pins[we-1].ljust(5), flash_id_cmds[i]["read_identifier"][0][0], flash_id_cmds[i]["read_identifier"][0][1], ' '.join(format(x, '02X') for x in cmp))
|
|
2261
2270
|
else:
|
|
2262
2271
|
flash_id_s += "[{:6X}/{:4X}] {:s}\n".format(flash_id_cmds[i]["read_identifier"][0][0], flash_id_cmds[i]["read_identifier"][0][1], ' '.join(format(x, '02X') for x in cmp))
|
|
2272
|
+
flash_id_cmds[i]["read_cfi"] = [ flash_id_cmds[i]["read_identifier"][0][0], 0x98 ]
|
|
2273
|
+
read_cfi_cmds.append(flash_id_cmds[i]["read_cfi"])
|
|
2263
2274
|
|
|
2264
2275
|
dprint(f"Found {len(flash_id_methods):d} result(s)")
|
|
2265
2276
|
self._cart_write_flash([[0, 0xFF]], True)
|
|
@@ -2293,10 +2304,55 @@ class LK_Device(ABC):
|
|
|
2293
2304
|
|
|
2294
2305
|
dprint("Compatible flash types:", [(index, supported_carts[index]["names"][0]) for index in flash_types])
|
|
2295
2306
|
|
|
2307
|
+
try:
|
|
2308
|
+
if len(flash_types) > 0 and "read_cfi" in supported_carts[flash_types[0]]["commands"]:
|
|
2309
|
+
read_cfi_cmd = supported_carts[flash_types[0]]["commands"]["read_cfi"]
|
|
2310
|
+
reset_cmd = supported_carts[flash_types[0]]["commands"]["reset"]
|
|
2311
|
+
else:
|
|
2312
|
+
if len(read_cfi_cmds) == 0:
|
|
2313
|
+
read_cfi_cmd = [ [0, 0x98] ]
|
|
2314
|
+
else:
|
|
2315
|
+
read_cfi_cmd = [ read_cfi_cmds[0] ]
|
|
2316
|
+
reset_cmd = flash_id_cmds[0]["reset"]
|
|
2317
|
+
self._cart_write_flash(read_cfi_cmd, flashcart=(self.MODE == "AGB"))
|
|
2318
|
+
cfi_buffer = self._cart_read(0, 0x400)
|
|
2319
|
+
self._cart_write_flash(reset_cmd, flashcart=(self.MODE == "AGB"))
|
|
2320
|
+
|
|
2321
|
+
if ".dev" in Util.VERSION_PEP440 or Util.DEBUG:
|
|
2322
|
+
with open(Util.CONFIG_PATH + "/debug_cfi.bin", "wb") as f: f.write(cfi_buffer)
|
|
2323
|
+
|
|
2324
|
+
found = False
|
|
2325
|
+
for o in ((0x20, 2), (0x10, 1)):
|
|
2326
|
+
magic = "{:s}{:s}{:s}".format(chr(cfi_buffer[o[0]]), chr(cfi_buffer[o[0] + (1 * o[1])]), chr(cfi_buffer[o[0] + (2 * o[1])]))
|
|
2327
|
+
dprint("CFI magic:", hex(o[0]), hex(o[0] + (1 * o[1])), hex(o[0] + (2 * o[1])), "=", str(magic))
|
|
2328
|
+
d_swap = (0, 0)
|
|
2329
|
+
if magic == "QRY": # D0D1 not swapped
|
|
2330
|
+
found = True
|
|
2331
|
+
elif magic == "RQZ": # D0D1 swapped
|
|
2332
|
+
d_swap = [(0, 1)]
|
|
2333
|
+
for j2 in range(0, len(d_swap)):
|
|
2334
|
+
for j in range(0, len(cfi_buffer)):
|
|
2335
|
+
cfi_buffer[j] = bitswap(cfi_buffer[j], d_swap[j2])
|
|
2336
|
+
found = True
|
|
2337
|
+
elif magic == "\x92\x91\x9A": # D0D1+D6D7 swapped
|
|
2338
|
+
d_swap = [( 0, 1 ), ( 6, 7 )]
|
|
2339
|
+
for j2 in range(0, len(d_swap)):
|
|
2340
|
+
for j in range(0, len(cfi_buffer)):
|
|
2341
|
+
cfi_buffer[j] = bitswap(cfi_buffer[j], d_swap[j2])
|
|
2342
|
+
if ".dev" in Util.VERSION_PEP440 or Util.DEBUG:
|
|
2343
|
+
with open(Util.CONFIG_PATH + "/debug_cfi_d0d1+d6d7.bin", "wb") as f: f.write(cfi_buffer)
|
|
2344
|
+
found = True
|
|
2345
|
+
if found: break
|
|
2346
|
+
if found is False:
|
|
2347
|
+
cfi_buffer = None
|
|
2348
|
+
except:
|
|
2349
|
+
cfi_buffer = None
|
|
2350
|
+
|
|
2296
2351
|
if cfi_buffer is None or len(cfi_buffer) < 0x400:
|
|
2297
2352
|
cfi = False
|
|
2298
2353
|
else:
|
|
2299
2354
|
cfi = ParseCFI(cfi_buffer)
|
|
2355
|
+
|
|
2300
2356
|
if cfi is not False:
|
|
2301
2357
|
cfi["raw"] = cfi_buffer
|
|
2302
2358
|
s = ""
|
|
@@ -2472,9 +2528,7 @@ class LK_Device(ABC):
|
|
|
2472
2528
|
|
|
2473
2529
|
# Firmware check L8
|
|
2474
2530
|
if self.FW["fw_ver"] < 8 and flashcart and "enable_pullups" in cart_type:
|
|
2475
|
-
|
|
2476
|
-
#return False
|
|
2477
|
-
print("{:s}Note: This cartridge may not be fully compatible with your {:s} device running an old or legacy firmware version.{:s}".format(ANSI.YELLOW, self.FW["pcb_name"], ANSI.RESET))
|
|
2531
|
+
print("{:s}Note: This cartridge may not be fully compatible with your {:s} device running an old or legacy firmware version.{:s}".format(ANSI.YELLOW, self.GetName(), ANSI.RESET))
|
|
2478
2532
|
del(cart_type["enable_pullups"])
|
|
2479
2533
|
# Firmware check L8
|
|
2480
2534
|
|
|
@@ -2535,9 +2589,6 @@ class LK_Device(ABC):
|
|
|
2535
2589
|
self.INFO["dump_info"]["agb_read_method"] = "3D Memory"
|
|
2536
2590
|
|
|
2537
2591
|
elif flashcart and "command_set" in cart_type and cart_type["command_set"] == "GBAMP":
|
|
2538
|
-
# if not self.CanPowerCycleCart():
|
|
2539
|
-
# self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge type is not compatible with your " + self.DEVICE_NAME + " hardware revision due to missing cartridge power cycling support.", "abortable":False})
|
|
2540
|
-
# return False
|
|
2541
2592
|
self.INFO["dump_info"]["agb_read_method"] = "GBA Movie Player"
|
|
2542
2593
|
if not "verify_write" in args: self.CartPowerCycleOrAskReconnect()
|
|
2543
2594
|
flashcart.Unlock()
|
|
@@ -2608,9 +2659,6 @@ class LK_Device(ABC):
|
|
|
2608
2659
|
else:
|
|
2609
2660
|
rom_banks = 1
|
|
2610
2661
|
rom_bank_size = 0x2000000
|
|
2611
|
-
|
|
2612
|
-
#if "header" in self.INFO["dump_info"] and "dacs_8m" in self.INFO["dump_info"]["header"] and self.INFO["dump_info"]["header"]["dacs_8m"] is True:
|
|
2613
|
-
# self.SetAGBReadMethod(0)
|
|
2614
2662
|
|
|
2615
2663
|
if self.ERROR: return
|
|
2616
2664
|
|
|
@@ -2635,9 +2683,12 @@ class LK_Device(ABC):
|
|
|
2635
2683
|
else:
|
|
2636
2684
|
self._write(self.DEVICE_CMD["DISABLE_PULLUPS"], wait=True)
|
|
2637
2685
|
dprint("Pullups disabled")
|
|
2686
|
+
|
|
2638
2687
|
if self.FW["fw_ver"] >= 12:
|
|
2639
|
-
if "
|
|
2640
|
-
|
|
2688
|
+
if self.MODE == "DMG":
|
|
2689
|
+
# Joey Jr bug workaround
|
|
2690
|
+
enable_pullup_wr = 2 if (("enable_pullup_wr" in cart_type and cart_type["enable_pullup_wr"] is True) or ("force_wr_pullup" in args and args["force_wr_pullup"] is True)) else 0
|
|
2691
|
+
self._set_fw_variable("PULLUPS_ENABLED", enable_pullup_wr)
|
|
2641
2692
|
|
|
2642
2693
|
buffer = bytearray(size)
|
|
2643
2694
|
max_length = self.MAX_BUFFER_READ
|
|
@@ -2661,6 +2712,8 @@ class LK_Device(ABC):
|
|
|
2661
2712
|
end_bank = math.ceil((buffer_pos + args["verify_len"]) / rom_bank_size)
|
|
2662
2713
|
rom_banks = end_bank
|
|
2663
2714
|
elif "bl_offset" in args:
|
|
2715
|
+
if "bl_layout" in args and args["bl_layout"] in (1, 2):
|
|
2716
|
+
args["bl_size"] <<= 1
|
|
2664
2717
|
buffer_pos = args["bl_offset"]
|
|
2665
2718
|
start_address = buffer_pos
|
|
2666
2719
|
end_address = args["bl_offset"] + args["bl_size"]
|
|
@@ -2765,7 +2818,13 @@ class LK_Device(ABC):
|
|
|
2765
2818
|
elif lives < 20:
|
|
2766
2819
|
lives = 20
|
|
2767
2820
|
|
|
2768
|
-
if file is not None:
|
|
2821
|
+
if file is not None:
|
|
2822
|
+
if "bl_layout" in args and args["bl_layout"] == 1:
|
|
2823
|
+
file.write(temp[0x0000:0x2000])
|
|
2824
|
+
elif "bl_layout" in args and args["bl_layout"] == 2:
|
|
2825
|
+
file.write(temp[0x2000:0x4000])
|
|
2826
|
+
else:
|
|
2827
|
+
file.write(temp)
|
|
2769
2828
|
buffer[pos_total:pos_total+len(temp)] = temp
|
|
2770
2829
|
pos_total += len(temp)
|
|
2771
2830
|
|
|
@@ -2942,9 +3001,12 @@ class LK_Device(ABC):
|
|
|
2942
3001
|
if "cart_type" in args and args["cart_type"] >= 0:
|
|
2943
3002
|
supported_carts = list(self.SUPPORTED_CARTS[self.MODE].values())
|
|
2944
3003
|
cart_type = copy.deepcopy(supported_carts[args["cart_type"]])
|
|
3004
|
+
|
|
2945
3005
|
if self.FW["fw_ver"] >= 12:
|
|
2946
|
-
if "
|
|
2947
|
-
|
|
3006
|
+
if self.MODE == "DMG":
|
|
3007
|
+
# Joey Jr bug workaround
|
|
3008
|
+
enable_pullup_wr = 2 if (("enable_pullup_wr" in cart_type and cart_type["enable_pullup_wr"] is True) or ("force_wr_pullup" in args and args["force_wr_pullup"] is True)) else 0
|
|
3009
|
+
self._set_fw_variable("PULLUPS_ENABLED", enable_pullup_wr)
|
|
2948
3010
|
|
|
2949
3011
|
self._set_fw_variable("STATUS_REGISTER_MASK", 0x80)
|
|
2950
3012
|
self._set_fw_variable("STATUS_REGISTER_VALUE", 0x80)
|
|
@@ -2960,7 +3022,9 @@ class LK_Device(ABC):
|
|
|
2960
3022
|
save_size = args["save_size"]
|
|
2961
3023
|
else:
|
|
2962
3024
|
save_size = Util.DMG_Header_RAM_Sizes_Flasher_Map[Util.DMG_Header_RAM_Sizes_Map.index(args["save_type"])]
|
|
3025
|
+
|
|
2963
3026
|
ram_banks = _mbc.GetRAMBanks(save_size)
|
|
3027
|
+
|
|
2964
3028
|
buffer_len = min(0x200, _mbc.GetRAMBankSize())
|
|
2965
3029
|
self._write(self.DEVICE_CMD["SET_MODE_DMG"], wait=self.FW["fw_ver"] >= 12)
|
|
2966
3030
|
self._set_fw_variable("DMG_WRITE_CS_PULSE", 0)
|
|
@@ -3121,6 +3185,9 @@ class LK_Device(ABC):
|
|
|
3121
3185
|
if args["mode"] == 2: # Backup
|
|
3122
3186
|
action = "SAVE_READ"
|
|
3123
3187
|
buffer = bytearray()
|
|
3188
|
+
if self.MODE == "DMG" and args["save_type"] == 0x204: # Unlicensed PHOTO!
|
|
3189
|
+
ram_banks = 16
|
|
3190
|
+
|
|
3124
3191
|
elif args["mode"] == 3: # Restore
|
|
3125
3192
|
action = "SAVE_WRITE"
|
|
3126
3193
|
self.INFO["save_erase"] = args["erase"]
|
|
@@ -3128,6 +3195,9 @@ class LK_Device(ABC):
|
|
|
3128
3195
|
buffer = bytearray([ empty_data_byte ] * save_size)
|
|
3129
3196
|
if self.MODE == "DMG" and _mbc.GetName() == "Xploder GB":
|
|
3130
3197
|
buffer[0] = 0x00
|
|
3198
|
+
elif self.MODE == "DMG" and _mbc.GetName() == "MAC-GBD":
|
|
3199
|
+
buffer[0x11B2:0x11D7] = bytearray.fromhex("FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF4D616769631115")
|
|
3200
|
+
buffer[0x11D7:0x11FC] = buffer[0x11B2:0x11D7]
|
|
3131
3201
|
else:
|
|
3132
3202
|
if args["path"] is None:
|
|
3133
3203
|
if "buffer" in args:
|
|
@@ -3138,16 +3208,18 @@ class LK_Device(ABC):
|
|
|
3138
3208
|
with open(args["path"], "rb") as f:
|
|
3139
3209
|
buffer = bytearray(f.read())
|
|
3140
3210
|
|
|
3211
|
+
if self.MODE == "DMG" and args["save_type"] == 0x204: # Unlicensed PHOTO!
|
|
3212
|
+
ram_banks = 16
|
|
3213
|
+
if len(buffer) <= 0x20000:
|
|
3214
|
+
save_size = len(buffer)
|
|
3215
|
+
args["save_type"] = 0x04
|
|
3216
|
+
|
|
3141
3217
|
# Fill too small file
|
|
3142
3218
|
if not (self.MODE == "AGB" and args["save_type"] == 6): # Not DACS
|
|
3143
3219
|
if args["mode"] == 3:
|
|
3144
3220
|
while len(buffer) < save_size:
|
|
3145
3221
|
buffer += bytearray(buffer)
|
|
3146
3222
|
|
|
3147
|
-
#if self.MODE == "AGB" and "ereader" in self.INFO and self.INFO["ereader"] is True: # e-Reader
|
|
3148
|
-
# buffer[0xFF80:0x10000] = bytearray([0] * 0x80)
|
|
3149
|
-
# buffer[0x1FF80:0x20000] = bytearray([0] * 0x80)
|
|
3150
|
-
|
|
3151
3223
|
# Main loop
|
|
3152
3224
|
if not (args["mode"] == 2 and "verify_write" in args and args["verify_write"]):
|
|
3153
3225
|
self.INFO["action"] = self.ACTIONS[action]
|
|
@@ -3198,10 +3270,6 @@ class LK_Device(ABC):
|
|
|
3198
3270
|
else:
|
|
3199
3271
|
dprint("Unknown bank switching method")
|
|
3200
3272
|
time.sleep(0.05)
|
|
3201
|
-
|
|
3202
|
-
# if "detect" in args and args["detect"] is True:
|
|
3203
|
-
# start_address = end_address - 64
|
|
3204
|
-
# buffer_len = 64
|
|
3205
3273
|
|
|
3206
3274
|
max_length = 64
|
|
3207
3275
|
dprint("start_address=0x{:X}, end_address=0x{:X}, buffer_len=0x{:X}, buffer_offset=0x{:X}".format(start_address, end_address, buffer_len, buffer_offset))
|
|
@@ -3259,7 +3327,6 @@ class LK_Device(ABC):
|
|
|
3259
3327
|
continue
|
|
3260
3328
|
|
|
3261
3329
|
if xe == 2 and in_temp[0] != in_temp[1]:
|
|
3262
|
-
# print(in_temp[0], in_temp[1], sep="\n")
|
|
3263
3330
|
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"Failed to read save data consistently. Please ensure that the cartridge contacts are clean.", "abortable":False})
|
|
3264
3331
|
return False
|
|
3265
3332
|
|
|
@@ -3381,11 +3448,6 @@ class LK_Device(ABC):
|
|
|
3381
3448
|
|
|
3382
3449
|
pos += buffer_len
|
|
3383
3450
|
buffer_offset += buffer_len
|
|
3384
|
-
|
|
3385
|
-
# if "detect" in args and args["detect"] is True:
|
|
3386
|
-
# buffer += bytearray(end_address - 64)
|
|
3387
|
-
# pos += end_address - 64
|
|
3388
|
-
# buffer_offset += end_address - 64
|
|
3389
3451
|
|
|
3390
3452
|
verified = False
|
|
3391
3453
|
if args["mode"] == 2: # Backup
|
|
@@ -3421,6 +3483,13 @@ class LK_Device(ABC):
|
|
|
3421
3483
|
if self.MODE == "AGB" and cart_type is not None and "flash_bank_select_type" in cart_type and cart_type["flash_bank_select_type"] == 1:
|
|
3422
3484
|
buffer[5] = sram_5
|
|
3423
3485
|
|
|
3486
|
+
# PHOTO! rolls
|
|
3487
|
+
if self.MODE == "DMG" and args["save_type"] == 0x204:
|
|
3488
|
+
for i in range(8, 64):
|
|
3489
|
+
_mbc.SelectBankROM(i)
|
|
3490
|
+
buffer += self.ReadROM(0x4000, 0x4000)
|
|
3491
|
+
self.SetProgress({"action":"UPDATE_POS", "pos":len(buffer)})
|
|
3492
|
+
|
|
3424
3493
|
if args["path"] is not None:
|
|
3425
3494
|
if self.MODE == "DMG" and _mbc.GetName() == "MBC2":
|
|
3426
3495
|
for i in range(0, len(buffer)):
|
|
@@ -3447,11 +3516,21 @@ class LK_Device(ABC):
|
|
|
3447
3516
|
advance = "rtc_advance" in args and args["rtc_advance"]
|
|
3448
3517
|
self.SetProgress({"action":"UPDATE_RTC", "method":"write"})
|
|
3449
3518
|
if self.MODE == "DMG" and args["rtc"] is True:
|
|
3519
|
+
if "erase" in args and args["erase"] is True:
|
|
3520
|
+
buffer += bytearray([0] * _mbc.GetRTCBufferSize())
|
|
3450
3521
|
_mbc.WriteRTC(buffer[-_mbc.GetRTCBufferSize():], advance=advance)
|
|
3451
3522
|
elif self.MODE == "AGB":
|
|
3523
|
+
if "erase" in args and args["erase"] is True:
|
|
3524
|
+
buffer += bytearray([0xFF] * 0x10)
|
|
3452
3525
|
_agb_gpio = AGB_GPIO(args={"rtc":True}, cart_write_fncptr=self._cart_write, cart_read_fncptr=self._cart_read, cart_powercycle_fncptr=self.CartPowerCycleOrAskReconnect, clk_toggle_fncptr=self._clk_toggle)
|
|
3453
3526
|
_agb_gpio.WriteRTC(buffer[-0x10:], advance=advance)
|
|
3454
3527
|
|
|
3528
|
+
# PHOTO! rolls
|
|
3529
|
+
if self.MODE == "DMG" and args["save_type"] == 0x204 and "cart_type" in args and args["cart_type"] != -1:
|
|
3530
|
+
if len(buffer) > 0x20000:
|
|
3531
|
+
self._FlashROM({'buffer': buffer[0x20000:0x100000], 'path':"", 'cart_type': args["cart_type"], 'override_voltage': False, 'prefer_chip_erase': False, 'fast_read_mode': True, 'verify_write': False, 'fix_header': False, 'fix_bootlogo': False, 'mbc': 252, 'bl_offset': 0x20000, 'bl_size': 0xE0000, 'bl_layout': 0, 'bl_save': True, 'flash_offset': 0x20000, 'flash_size': 0xE0000, 'mode': 4, 'photo_mode': True})
|
|
3532
|
+
args["verify_write"] = False
|
|
3533
|
+
|
|
3455
3534
|
self.SetProgress({"action":"UPDATE_POS", "pos":len(buffer), "force_update":True})
|
|
3456
3535
|
|
|
3457
3536
|
# ↓↓↓ Write verify
|
|
@@ -3540,6 +3619,7 @@ class LK_Device(ABC):
|
|
|
3540
3619
|
end_bank = 0
|
|
3541
3620
|
pos_from = 0
|
|
3542
3621
|
verify_len = 0
|
|
3622
|
+
enable_pullup_wr = False
|
|
3543
3623
|
|
|
3544
3624
|
if "buffer" in args:
|
|
3545
3625
|
data_import = args["buffer"]
|
|
@@ -3552,6 +3632,20 @@ class LK_Device(ABC):
|
|
|
3552
3632
|
if "start_addr" in args and args["start_addr"] > 0:
|
|
3553
3633
|
data_import = bytearray(b'\xFF' * args["start_addr"]) + data_import
|
|
3554
3634
|
|
|
3635
|
+
# Batteryless SRAM
|
|
3636
|
+
if "bl_layout" in args and args["bl_layout"] in (1, 2):
|
|
3637
|
+
args["bl_size"] <<= 1
|
|
3638
|
+
args["flash_size"] <<= 1
|
|
3639
|
+
bl_data_import = bytearray(b'\xFF' * args["bl_size"])
|
|
3640
|
+
|
|
3641
|
+
if args["bl_layout"] == 1:
|
|
3642
|
+
for i in range(0, args["bl_size"] // 0x4000):
|
|
3643
|
+
bl_data_import[i*0x4000:i*0x4000+0x2000] = data_import[i*0x2000:i*0x2000+0x2000]
|
|
3644
|
+
elif args["bl_layout"] == 2:
|
|
3645
|
+
for i in range(0, args["bl_size"] // 0x4000):
|
|
3646
|
+
bl_data_import[i*0x4000+0x2000:i*0x4000+0x2000+0x2000] = data_import[i*0x2000:i*0x2000+0x2000]
|
|
3647
|
+
data_import = bl_data_import
|
|
3648
|
+
|
|
3555
3649
|
# Pad data
|
|
3556
3650
|
if len(data_import) > 0:
|
|
3557
3651
|
if len(data_import) < 0x400:
|
|
@@ -3594,24 +3688,23 @@ class LK_Device(ABC):
|
|
|
3594
3688
|
|
|
3595
3689
|
supported_carts = list(self.SUPPORTED_CARTS[self.MODE].values())
|
|
3596
3690
|
cart_type = copy.deepcopy(supported_carts[args["cart_type"]])
|
|
3691
|
+
try:
|
|
3692
|
+
cart_name = cart_type["names"][0]
|
|
3693
|
+
except:
|
|
3694
|
+
cart_name = "Unknown"
|
|
3695
|
+
|
|
3597
3696
|
if cart_type == "RETAIL": return False # Generic ROM Cartridge is not flashable
|
|
3598
3697
|
|
|
3599
|
-
#
|
|
3600
|
-
# if "power_cycle" in cart_type and cart_type["power_cycle"] is True and not self.CanPowerCycleCart():
|
|
3601
|
-
# self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge type is not flashable using FlashGBX and your " + self.DEVICE_NAME + " hardware revision due to missing cartridge power cycling support.", "abortable":False})
|
|
3602
|
-
# return False
|
|
3603
|
-
# Special carts
|
|
3604
|
-
# Firmware check L1
|
|
3698
|
+
# Firmware check L2
|
|
3605
3699
|
if (cart_type["type"] == "DMG" and "write_pin" in cart_type and cart_type["write_pin"] == "WR+RESET" and self.FW["fw_ver"] < 2) or (self.FW["fw_ver"] < 2 and ("pulse_reset_after_write" in cart_type and cart_type["pulse_reset_after_write"] is True)):
|
|
3606
|
-
#self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge type is not supported by FlashGBX using your " + self.DEVICE_NAME + " hardware revision and/or firmware version.", "abortable":False})
|
|
3607
3700
|
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge type requires at least firmware version L2.", "abortable":False})
|
|
3608
3701
|
return False
|
|
3609
|
-
# Firmware check L1
|
|
3610
3702
|
# Firmware check L2
|
|
3703
|
+
# Firmware check L3
|
|
3611
3704
|
if (self.FW["fw_ver"] < 3 and ("command_set" in cart_type and cart_type["command_set"] == "SHARP") and ("buffer_write" in cart_type["commands"])):
|
|
3612
3705
|
print("{:s}Note: Update your {:s} firmware to version L3 or higher for a better transfer rate with this cartridge.{:s}".format(ANSI.YELLOW, self.DEVICE_NAME, ANSI.RESET))
|
|
3613
3706
|
del(cart_type["commands"]["buffer_write"])
|
|
3614
|
-
# Firmware check
|
|
3707
|
+
# Firmware check L3
|
|
3615
3708
|
# Firmware check L5
|
|
3616
3709
|
if (self.FW["fw_ver"] < 5 and ("flash_commands_on_bank_1" in cart_type and cart_type["flash_commands_on_bank_1"] is True)):
|
|
3617
3710
|
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge type requires at least firmware version L5.", "abortable":False})
|
|
@@ -3622,21 +3715,25 @@ class LK_Device(ABC):
|
|
|
3622
3715
|
# Firmware check L5
|
|
3623
3716
|
# Firmware check L8
|
|
3624
3717
|
if (self.FW["fw_ver"] < 8 and "enable_pullups" in cart_type and cart_type["enable_pullups"] is True):
|
|
3625
|
-
|
|
3626
|
-
#return False
|
|
3627
|
-
print("{:s}Note: This cartridge may not be fully compatible with your {:s} device running an old or legacy firmware version.{:s}".format(ANSI.YELLOW, self.FW["pcb_name"], ANSI.RESET))
|
|
3718
|
+
print("{:s}Note: This cartridge may not be fully compatible with your {:s} device running an old or legacy firmware version.{:s}".format(ANSI.YELLOW, self.GetName(), ANSI.RESET))
|
|
3628
3719
|
del(cart_type["enable_pullups"])
|
|
3629
3720
|
# Firmware check L8
|
|
3630
3721
|
# Firmware check L12
|
|
3631
3722
|
if (self.FW["fw_ver"] < 12 and "set_irq_high" in cart_type and cart_type["set_irq_high"] is True):
|
|
3632
|
-
|
|
3633
|
-
#return False
|
|
3634
|
-
print("{:s}Note: This cartridge may not be fully compatible with your {:s} device running an old or legacy firmware version.{:s}".format(ANSI.YELLOW, self.FW["pcb_name"], ANSI.RESET))
|
|
3723
|
+
print("{:s}Note: This cartridge may not be fully compatible with your {:s} device until updated to a newer firmware version.{:s}".format(ANSI.YELLOW, self.GetName(), ANSI.RESET))
|
|
3635
3724
|
del(cart_type["set_irq_high"])
|
|
3636
3725
|
if (self.FW["fw_ver"] < 12 and "status_register_mask" in cart_type):
|
|
3637
|
-
self.
|
|
3726
|
+
if self.FW["pcb_name"] in ("GBxCart RW", ""):
|
|
3727
|
+
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge type requires a different firmware version. Please update your GBxCart RW firmware using the older FlashGBX v4.3 and try again.", "abortable":False})
|
|
3728
|
+
else:
|
|
3729
|
+
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge type requires at least firmware version L12.", "abortable":False})
|
|
3638
3730
|
return False
|
|
3639
3731
|
# Firmware check L12
|
|
3732
|
+
# Firmware check L14
|
|
3733
|
+
if (self.FW["fw_ver"] < 14 and "set_audio_high" in cart_type and cart_type["set_audio_high"] is True):
|
|
3734
|
+
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"This cartridge type requires at least firmware version L14.", "abortable":False})
|
|
3735
|
+
return False
|
|
3736
|
+
# Firmware check L14
|
|
3640
3737
|
|
|
3641
3738
|
# Ensure cart is powered
|
|
3642
3739
|
if self.CanPowerCycleCart(): self.CartPowerOn()
|
|
@@ -3668,7 +3765,7 @@ class LK_Device(ABC):
|
|
|
3668
3765
|
flashcart = Flashcart(config=cart_type, fncptr=fc_fncptr)
|
|
3669
3766
|
|
|
3670
3767
|
rumble = "rumble" in flashcart.CONFIG and flashcart.CONFIG["rumble"] is True
|
|
3671
|
-
|
|
3768
|
+
|
|
3672
3769
|
# ↓↓↓ Set Voltage
|
|
3673
3770
|
if args["override_voltage"] is not False:
|
|
3674
3771
|
if args["override_voltage"] == 5:
|
|
@@ -3680,20 +3777,22 @@ class LK_Device(ABC):
|
|
|
3680
3777
|
elif flashcart.GetVoltage() == 5:
|
|
3681
3778
|
self._write(self.DEVICE_CMD["SET_VOLTAGE_5V"], wait=self.FW["fw_ver"] >= 12)
|
|
3682
3779
|
# ↑↑↑ Set Voltage
|
|
3683
|
-
|
|
3780
|
+
|
|
3684
3781
|
# ↓↓↓ Pad data for full chip erase on sector erase mode
|
|
3685
3782
|
if not flashcart.SupportsChipErase() and flashcart.SupportsSectorErase() and args["prefer_chip_erase"]:
|
|
3686
3783
|
print("{:s}Note: Chip erase mode is not supported for this flash cartridge type. Sector erase mode will be used.{:s}\n".format(ANSI.YELLOW, ANSI.RESET))
|
|
3687
|
-
|
|
3688
|
-
if
|
|
3689
|
-
|
|
3690
|
-
|
|
3691
|
-
|
|
3692
|
-
|
|
3693
|
-
pad_len
|
|
3694
|
-
|
|
3784
|
+
# Pad data if the user wants to erase the entire cartridge
|
|
3785
|
+
if data_import == bytearray([0xFF] * len(data_import)):
|
|
3786
|
+
flash_size = flashcart.GetFlashSize()
|
|
3787
|
+
if flash_size is not False and len(data_import) < flash_size:
|
|
3788
|
+
# Pad with FF till the end (with MemoryError fix)
|
|
3789
|
+
pad_len = flash_size - len(data_import)
|
|
3790
|
+
while pad_len > 0x2000000:
|
|
3791
|
+
data_import += bytearray([0xFF] * 0x2000000)
|
|
3792
|
+
pad_len -= 0x2000000
|
|
3793
|
+
data_import += bytearray([0xFF] * (flash_size - len(data_import)))
|
|
3695
3794
|
# ↑↑↑ Pad data for full chip erase on sector erase mode
|
|
3696
|
-
|
|
3795
|
+
|
|
3697
3796
|
# ↓↓↓ Flashcart configuration
|
|
3698
3797
|
if self.FW["fw_ver"] >= 8:
|
|
3699
3798
|
if "enable_pullups" in cart_type:
|
|
@@ -3704,9 +3803,11 @@ class LK_Device(ABC):
|
|
|
3704
3803
|
self._write(self.DEVICE_CMD["DISABLE_PULLUPS"], wait=True)
|
|
3705
3804
|
dprint("Pullups disabled")
|
|
3706
3805
|
if self.FW["fw_ver"] >= 12:
|
|
3707
|
-
if "
|
|
3708
|
-
|
|
3709
|
-
|
|
3806
|
+
if self.MODE == "DMG":
|
|
3807
|
+
# Joey Jr bug workaround
|
|
3808
|
+
enable_pullup_wr = 2 if (("enable_pullup_wr" in cart_type and cart_type["enable_pullup_wr"] is True) or ("force_wr_pullup" in args and args["force_wr_pullup"] is True)) else 0
|
|
3809
|
+
self._set_fw_variable("PULLUPS_ENABLED", enable_pullup_wr)
|
|
3810
|
+
elif self.MODE == "AGB":
|
|
3710
3811
|
self._set_fw_variable("AGB_IRQ_ENABLED", 1 if "set_irq_high" in cart_type else 0)
|
|
3711
3812
|
|
|
3712
3813
|
_mbc = None
|
|
@@ -3793,17 +3894,13 @@ class LK_Device(ABC):
|
|
|
3793
3894
|
temp = 0
|
|
3794
3895
|
if command_set_type == "AMD":
|
|
3795
3896
|
temp = 0x01
|
|
3796
|
-
#self._write(0x01) # FLASH_COMMAND_SET_AMD
|
|
3797
|
-
#self._set_fw_variable("FLASH_SHARP_VERIFY_SR", 0)
|
|
3798
3897
|
dprint("Using AMD command set")
|
|
3799
3898
|
elif command_set_type == "INTEL":
|
|
3800
3899
|
temp = 0x02
|
|
3801
|
-
#self._write(0x02) # FLASH_COMMAND_SET_INTEL
|
|
3802
3900
|
self._set_fw_variable("FLASH_SHARP_VERIFY_SR", 0)
|
|
3803
3901
|
dprint("Using Intel command set")
|
|
3804
3902
|
elif command_set_type == "SHARP":
|
|
3805
3903
|
temp = 0x02
|
|
3806
|
-
#self._write(0x02) # FLASH_COMMAND_SET_INTEL
|
|
3807
3904
|
self._set_fw_variable("FLASH_SHARP_VERIFY_SR", 1)
|
|
3808
3905
|
dprint("Using Sharp/Intel command set")
|
|
3809
3906
|
elif command_set_type in ("GBMEMORY", "DMG-MBC5-32M-FLASH"):
|
|
@@ -3944,6 +4041,8 @@ class LK_Device(ABC):
|
|
|
3944
4041
|
_mbc.SelectBankROM(1)
|
|
3945
4042
|
if we != 0x00:
|
|
3946
4043
|
self._set_fw_variable("FLASH_WE_PIN", we)
|
|
4044
|
+
if self.FW["fw_ver"] >= 14 and "set_audio_high" in cart_type:
|
|
4045
|
+
self._set_fw_variable("DMG_AUDIO_ENABLED", 1 if "set_audio_high" in cart_type else 0)
|
|
3947
4046
|
# ↑↑↑ Preparations
|
|
3948
4047
|
|
|
3949
4048
|
# ↓↓↓ Read Flash ID
|
|
@@ -3970,8 +4069,6 @@ class LK_Device(ABC):
|
|
|
3970
4069
|
if len(sector_offsets) > 0:
|
|
3971
4070
|
flash_capacity = sector_offsets[-1][0] + sector_offsets[-1][1]
|
|
3972
4071
|
if flash_capacity < len(data_import) and not (flashcart.SupportsChipErase() and args["prefer_chip_erase"]):
|
|
3973
|
-
#self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"There are not enough flash sectors available to write this ROM. The maximum capacity is {:s}.".format(Util.formatFileSize(size=flash_capacity, asInt=False)), "abortable":False})
|
|
3974
|
-
#return False
|
|
3975
4072
|
sector_offsets = flashcart.GetSectorOffsets(rom_size=len(data_import), rom_bank_size=rom_bank_size)
|
|
3976
4073
|
|
|
3977
4074
|
sector_offsets_hash = base64.urlsafe_b64encode(hashlib.sha1(str(sector_offsets).encode("UTF-8")).digest()).decode("ASCII", "ignore")[:4]
|
|
@@ -4026,7 +4123,6 @@ class LK_Device(ABC):
|
|
|
4026
4123
|
bl_sectors = []
|
|
4027
4124
|
for sector in sector_offsets:
|
|
4028
4125
|
if flash_offset > sector[0]: continue
|
|
4029
|
-
#if len(bl_sectors) > 0 and (flash_offset + flash_size) < (sector[0] + sector[1]): break
|
|
4030
4126
|
if (flash_offset + flash_size) < sector[0]: break
|
|
4031
4127
|
bl_sectors.append(sector)
|
|
4032
4128
|
write_sectors = bl_sectors
|
|
@@ -4040,7 +4136,7 @@ class LK_Device(ABC):
|
|
|
4040
4136
|
|
|
4041
4137
|
dprint("Sectors to update:", write_sectors)
|
|
4042
4138
|
# ↑↑↑ Read Sector Map
|
|
4043
|
-
|
|
4139
|
+
|
|
4044
4140
|
# ↓↓↓ Chip erase
|
|
4045
4141
|
chip_erase = False
|
|
4046
4142
|
if flashcart.SupportsChipErase() and not flash_offset > 0:
|
|
@@ -4055,7 +4151,7 @@ class LK_Device(ABC):
|
|
|
4055
4151
|
self.SetProgress({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"No erase method available.", "abortable":False})
|
|
4056
4152
|
return False
|
|
4057
4153
|
# ↑↑↑ Chip erase
|
|
4058
|
-
|
|
4154
|
+
|
|
4059
4155
|
# ↓↓↓ Flash Write
|
|
4060
4156
|
if chip_erase:
|
|
4061
4157
|
write_sectors = [[ 0, len(data_import) ]]
|
|
@@ -4064,9 +4160,10 @@ class LK_Device(ABC):
|
|
|
4064
4160
|
elif len(write_sectors) == 0:
|
|
4065
4161
|
write_sectors = sector_offsets
|
|
4066
4162
|
|
|
4067
|
-
|
|
4163
|
+
if not "photo_mode" in args:
|
|
4164
|
+
self.SetProgress({"action":"INITIALIZE", "method":"ROM_WRITE", "size":len(data_import), "flash_offset":flash_offset, "sector_count":len(write_sectors)})
|
|
4165
|
+
self.INFO["action"] = self.ACTIONS["ROM_WRITE"]
|
|
4068
4166
|
self.SetProgress({"action":"UPDATE_POS", "pos":flash_offset})
|
|
4069
|
-
self.INFO["action"] = self.ACTIONS["ROM_WRITE"]
|
|
4070
4167
|
|
|
4071
4168
|
if smallest_sector_size is not False:
|
|
4072
4169
|
buffer_len = smallest_sector_size
|
|
@@ -4121,82 +4218,79 @@ class LK_Device(ABC):
|
|
|
4121
4218
|
bank = start_bank
|
|
4122
4219
|
|
|
4123
4220
|
# ↓↓↓ Check if data matches already
|
|
4124
|
-
if self.FW["fw_ver"] >=
|
|
4125
|
-
|
|
4126
|
-
|
|
4127
|
-
|
|
4128
|
-
|
|
4129
|
-
|
|
4130
|
-
|
|
4131
|
-
|
|
4132
|
-
if
|
|
4133
|
-
|
|
4134
|
-
|
|
4221
|
+
if not chip_erase and self.FW["fw_ver"] >= 12 and "compare_sectors" in args and args["compare_sectors"] is True and not (flashcart and cart_type["command_set"] == "GBAMP"):
|
|
4222
|
+
buffer_pos_matchcheck = buffer_pos
|
|
4223
|
+
verified = False
|
|
4224
|
+
ts_se_start = time.time()
|
|
4225
|
+
while bank < end_bank:
|
|
4226
|
+
status = None
|
|
4227
|
+
# ↓↓↓ Switch ROM bank
|
|
4228
|
+
if self.MODE == "DMG":
|
|
4229
|
+
if _mbc.ResetBeforeBankChange(bank) is True:
|
|
4230
|
+
dprint("Resetting the MBC")
|
|
4231
|
+
self._write(self.DEVICE_CMD["DMG_MBC_RESET"], wait=True)
|
|
4232
|
+
(start_address, bank_size) = _mbc.SelectBankROM(bank)
|
|
4233
|
+
if flashcart.PulseResetAfterWrite():
|
|
4234
|
+
if bank == 0:
|
|
4235
|
+
if self.FW["fw_ver"] < 2:
|
|
4236
|
+
self._write(self.DEVICE_CMD["OFW_GB_CART_MODE"])
|
|
4237
|
+
else:
|
|
4238
|
+
self._write(self.DEVICE_CMD["SET_MODE_DMG"], wait=self.FW["fw_ver"] >= 12)
|
|
4135
4239
|
self._write(self.DEVICE_CMD["DMG_MBC_RESET"], wait=True)
|
|
4136
|
-
|
|
4137
|
-
|
|
4138
|
-
|
|
4139
|
-
|
|
4140
|
-
|
|
4141
|
-
|
|
4142
|
-
|
|
4143
|
-
|
|
4144
|
-
# else:
|
|
4145
|
-
# self._write(self.DEVICE_CMD["OFW_GB_FLASH_BANK_1_COMMAND_WRITES"])
|
|
4146
|
-
self._set_fw_variable("DMG_ROM_BANK", bank)
|
|
4147
|
-
|
|
4148
|
-
buffer_len = min(buffer_len, bank_size)
|
|
4149
|
-
if "start_addr" in flashcart.CONFIG and bank == 0: start_address = flashcart.CONFIG["start_addr"]
|
|
4150
|
-
end_address = start_address + bank_size
|
|
4151
|
-
start_address += (buffer_pos % rom_bank_size)
|
|
4152
|
-
if end_address > start_address + sector[1]:
|
|
4153
|
-
end_address = start_address + sector[1]
|
|
4154
|
-
|
|
4155
|
-
elif self.MODE == "AGB":
|
|
4156
|
-
if "flash_bank_select_type" in cart_type and cart_type["flash_bank_select_type"] > 0:
|
|
4157
|
-
if bank != current_bank:
|
|
4158
|
-
flashcart.Reset(full_reset=True)
|
|
4159
|
-
flashcart.SelectBankROM(bank)
|
|
4160
|
-
temp = end_address - start_address
|
|
4161
|
-
start_address %= cart_type["flash_bank_size"]
|
|
4162
|
-
end_address = min(cart_type["flash_bank_size"], start_address + temp)
|
|
4163
|
-
current_bank = bank
|
|
4164
|
-
# ↑↑↑ Switch ROM bank
|
|
4240
|
+
self._set_fw_variable("DMG_ROM_BANK", bank)
|
|
4241
|
+
|
|
4242
|
+
buffer_len = min(buffer_len, bank_size)
|
|
4243
|
+
if "start_addr" in flashcart.CONFIG and bank == 0: start_address = flashcart.CONFIG["start_addr"]
|
|
4244
|
+
end_address = start_address + bank_size
|
|
4245
|
+
start_address += (buffer_pos % rom_bank_size)
|
|
4246
|
+
if end_address > start_address + sector[1]:
|
|
4247
|
+
end_address = start_address + sector[1]
|
|
4165
4248
|
|
|
4166
|
-
|
|
4167
|
-
|
|
4168
|
-
|
|
4169
|
-
|
|
4170
|
-
|
|
4171
|
-
|
|
4172
|
-
|
|
4173
|
-
|
|
4249
|
+
elif self.MODE == "AGB":
|
|
4250
|
+
if "flash_bank_select_type" in cart_type and cart_type["flash_bank_select_type"] > 0:
|
|
4251
|
+
if bank != current_bank:
|
|
4252
|
+
flashcart.Reset(full_reset=True)
|
|
4253
|
+
flashcart.SelectBankROM(bank)
|
|
4254
|
+
temp = end_address - start_address
|
|
4255
|
+
start_address %= cart_type["flash_bank_size"]
|
|
4256
|
+
end_address = min(cart_type["flash_bank_size"], start_address + temp)
|
|
4257
|
+
current_bank = bank
|
|
4258
|
+
# ↑↑↑ Switch ROM bank
|
|
4259
|
+
|
|
4260
|
+
pos = start_address
|
|
4261
|
+
#dprint("pos=0x{:X}, buffer_pos=0x{:X}, start_address=0x{:X}, end_address=0x{:X}".format(pos, buffer_pos_matchcheck, start_address, end_address))
|
|
4262
|
+
verified = self.CompareCRC32(buffer=data_import, offset=buffer_pos_matchcheck, length=end_address - pos, address=pos, flashcart=flashcart, reset=True, mbc=_mbc, bank=bank)
|
|
4263
|
+
self.SetProgress({"action":"UPDATE_POS", "pos":buffer_pos_matchcheck})
|
|
4264
|
+
if verified is not True:
|
|
4265
|
+
break
|
|
4266
|
+
buffer_pos_matchcheck += (end_address - pos)
|
|
4267
|
+
bank += 1
|
|
4174
4268
|
|
|
4175
|
-
|
|
4176
|
-
|
|
4177
|
-
|
|
4178
|
-
|
|
4179
|
-
|
|
4180
|
-
|
|
4181
|
-
|
|
4182
|
-
|
|
4183
|
-
|
|
4184
|
-
|
|
4185
|
-
|
|
4186
|
-
|
|
4187
|
-
|
|
4188
|
-
|
|
4189
|
-
|
|
4190
|
-
|
|
4191
|
-
|
|
4192
|
-
|
|
4193
|
-
|
|
4194
|
-
|
|
4195
|
-
|
|
4196
|
-
|
|
4197
|
-
|
|
4198
|
-
|
|
4199
|
-
|
|
4269
|
+
if verified is True:
|
|
4270
|
+
dprint("Skipping sector #{:d}, because the CRC32 matched".format(sector_pos))
|
|
4271
|
+
if flashcart.FlashCommandsOnBank1(): _mbc.SelectBankROM(bank)
|
|
4272
|
+
self.NO_PROG_UPDATE = True
|
|
4273
|
+
se_ret = flashcart.SectorErase(pos=pos, buffer_pos=buffer_pos, skip=verified)
|
|
4274
|
+
self.NO_PROG_UPDATE = False
|
|
4275
|
+
|
|
4276
|
+
if self.CANCEL:
|
|
4277
|
+
cancel_args = {"action":"ABORT", "abortable":False}
|
|
4278
|
+
cancel_args.update(self.CANCEL_ARGS)
|
|
4279
|
+
self.CANCEL_ARGS = {}
|
|
4280
|
+
self.ERROR_ARGS = {}
|
|
4281
|
+
self.SetProgress(cancel_args)
|
|
4282
|
+
if self.CanPowerCycleCart(): self.CartPowerCycle()
|
|
4283
|
+
return
|
|
4284
|
+
|
|
4285
|
+
ts_se_elapsed = time.time() - ts_se_start
|
|
4286
|
+
if se_ret:
|
|
4287
|
+
sector_size = se_ret
|
|
4288
|
+
dprint("Next sector size: 0x{:X}".format(sector_size))
|
|
4289
|
+
buffer_pos += sector_size
|
|
4290
|
+
continue
|
|
4291
|
+
else:
|
|
4292
|
+
verified = False
|
|
4293
|
+
bank = start_bank
|
|
4200
4294
|
# ↑↑↑ Check if data matches already
|
|
4201
4295
|
|
|
4202
4296
|
while bank < end_bank:
|
|
@@ -4210,7 +4304,6 @@ class LK_Device(ABC):
|
|
|
4210
4304
|
return
|
|
4211
4305
|
|
|
4212
4306
|
status = None
|
|
4213
|
-
#print("Bank:", bank, "...")
|
|
4214
4307
|
# ↓↓↓ Switch ROM bank
|
|
4215
4308
|
if self.MODE == "DMG":
|
|
4216
4309
|
if _mbc.ResetBeforeBankChange(bank) is True:
|
|
@@ -4224,8 +4317,6 @@ class LK_Device(ABC):
|
|
|
4224
4317
|
else:
|
|
4225
4318
|
self._write(self.DEVICE_CMD["SET_MODE_DMG"], wait=self.FW["fw_ver"] >= 12)
|
|
4226
4319
|
self._write(self.DEVICE_CMD["DMG_MBC_RESET"], wait=True)
|
|
4227
|
-
# else:
|
|
4228
|
-
# self._write(self.DEVICE_CMD["OFW_GB_FLASH_BANK_1_COMMAND_WRITES"])
|
|
4229
4320
|
self._set_fw_variable("DMG_ROM_BANK", bank)
|
|
4230
4321
|
|
|
4231
4322
|
buffer_len = min(buffer_len, bank_size)
|
|
@@ -4296,8 +4387,6 @@ class LK_Device(ABC):
|
|
|
4296
4387
|
status = self.WriteROM(address=pos, buffer=data_import[buffer_pos:buffer_pos+buffer_len], flash_buffer_size=flash_buffer_size, skip_init=(skip_init and not self.SKIPPING))
|
|
4297
4388
|
elif command_set_type == "DMG-MBC5-32M-FLASH" and self.FW["fw_ver"] < 12:
|
|
4298
4389
|
status = self.WriteROM_DMG_MBC5_32M_FLASH(address=pos, buffer=data_import[buffer_pos:buffer_pos+buffer_len], bank=bank)
|
|
4299
|
-
#elif command_set_type == "DMG-MBC5-32M-FLASH" and self.FW["fw_ver"] >= 12:
|
|
4300
|
-
# status = self.WriteROM(address=pos, buffer=data_import[buffer_pos:buffer_pos+buffer_len], flash_buffer_size=flash_buffer_size, skip_init=(skip_init and not self.SKIPPING))
|
|
4301
4390
|
elif command_set_type == "EEPROM":
|
|
4302
4391
|
status = self.WriteROM_DMG_EEPROM(address=pos, buffer=data_import[buffer_pos:buffer_pos+buffer_len], bank=bank, eeprom_buffer_size=256)
|
|
4303
4392
|
elif command_set_type == "BLAZE_XPLODER":
|
|
@@ -4348,21 +4437,22 @@ class LK_Device(ABC):
|
|
|
4348
4437
|
if "from_user" in self.CANCEL_ARGS and self.CANCEL_ARGS["from_user"]:
|
|
4349
4438
|
break
|
|
4350
4439
|
elif not self.DEVICE.is_open or self.DEVICE is None:
|
|
4351
|
-
self.CANCEL_ARGS.update({"info_type":"msgbox_critical", "info_msg":"An error occured while writing 0x{:X} bytes at position 0x{:X} ({:s}). Please re-connect the device and try again from the beginning.\n\nTroubleshooting advice:\n- Clean cartridge contacts\n- Avoid passive USB hubs and try different USB ports/cables\n- Check cartridge type selection{:s}\n\nStatus Register: {:s}".format(buffer_len, buffer_pos, Util.formatFileSize(size=buffer_pos, asInt=False), errmsg_mbc_selection, sr)})
|
|
4440
|
+
self.CANCEL_ARGS.update({"info_type":"msgbox_critical", "info_msg":"An error occured while writing 0x{:X} bytes at position 0x{:X} ({:s}). Please re-connect the device and try again from the beginning.\n\nTroubleshooting advice:\n- Clean cartridge contacts\n- Check soldering if it’s a DIY cartridge\n- Avoid passive USB hubs and try different USB ports/cables\n- Check cartridge type selection{:s}\n\nStatus Register: {:s}".format(buffer_len, buffer_pos, Util.formatFileSize(size=buffer_pos, asInt=False), errmsg_mbc_selection, sr)})
|
|
4352
4441
|
break
|
|
4353
4442
|
else:
|
|
4354
4443
|
if chip_erase: retry_hp = 0
|
|
4355
4444
|
if "iteration" in self.ERROR_ARGS and self.ERROR_ARGS["iteration"] > 0:
|
|
4356
4445
|
retry_hp -= 5
|
|
4357
4446
|
if retry_hp <= 0:
|
|
4358
|
-
self.CANCEL_ARGS.update({"info_type":"msgbox_critical", "info_msg":"Unstable connection detected while writing 0x{:X} bytes in iteration {:d} at position 0x{:X} ({:s}). Please re-connect the device and try again from the beginning.\n\nTroubleshooting advice:\n- Clean cartridge contacts\n- Avoid passive USB hubs and try different USB ports/cables\n\nStatus Register: {:s}".format(buffer_len, self.ERROR_ARGS["iteration"], buffer_pos, Util.formatFileSize(size=buffer_pos, asInt=False), sr)})
|
|
4447
|
+
self.CANCEL_ARGS.update({"info_type":"msgbox_critical", "info_msg":"Unstable connection detected while writing 0x{:X} bytes in iteration {:d} at position 0x{:X} ({:s}). Please re-connect the device and try again from the beginning.\n\nTroubleshooting advice:\n- Clean cartridge contacts\n- Check soldering if it’s a DIY cartridge\n- Avoid passive USB hubs and try different USB ports/cables\n\nStatus Register: {:s}".format(buffer_len, self.ERROR_ARGS["iteration"], buffer_pos, Util.formatFileSize(size=buffer_pos, asInt=False), sr)})
|
|
4359
4448
|
continue
|
|
4360
4449
|
else:
|
|
4361
4450
|
retry_hp -= 10
|
|
4362
4451
|
if retry_hp <= 0:
|
|
4363
|
-
|
|
4452
|
+
enable_pullup_wr_str = " (+ WR pullup)" if enable_pullup_wr == 2 else ""
|
|
4453
|
+
self.CANCEL_ARGS.update({"info_type":"msgbox_critical", "info_msg":"An error occured while writing 0x{:X} bytes at position 0x{:X} ({:s}). Please re-connect the device and try again from the beginning.\n\nTroubleshooting advice:\n- Clean cartridge contacts\n- Check soldering if it’s a DIY cartridge\n- Avoid passive USB hubs and try different USB ports/cables\n- Check cartridge type selection\n- Check cartridge ROM storage size (at least {:s} is required){:s}\n- Check cartridge profile used: {:s}{:s}\n- The cartridge may also be incompatible with your “{:s}” device\n\nStatus Register: {:s}".format(buffer_len, buffer_pos, Util.formatFileSize(size=buffer_pos, asInt=False), Util.formatFileSize(size=len(data_import), asInt=False), errmsg_mbc_selection, cart_name, enable_pullup_wr_str, self.GetFullNameLabel(), sr), "abortable":False})
|
|
4364
4454
|
continue
|
|
4365
|
-
|
|
4455
|
+
|
|
4366
4456
|
rev_buffer_pos = sector_offsets[sector_pos - 1][0]
|
|
4367
4457
|
buffer_pos = rev_buffer_pos
|
|
4368
4458
|
bank = start_bank
|
|
@@ -4396,10 +4486,6 @@ class LK_Device(ABC):
|
|
|
4396
4486
|
self._cart_write(pos, 0xFF)
|
|
4397
4487
|
if flashcart.Unlock() is False: return False
|
|
4398
4488
|
continue
|
|
4399
|
-
|
|
4400
|
-
self.CANCEL = True
|
|
4401
|
-
self.ERROR = True
|
|
4402
|
-
continue
|
|
4403
4489
|
|
|
4404
4490
|
skip_init = True
|
|
4405
4491
|
|
|
@@ -4425,6 +4511,8 @@ class LK_Device(ABC):
|
|
|
4425
4511
|
|
|
4426
4512
|
# ↓↓↓ Reset flash
|
|
4427
4513
|
flashcart.Reset(full_reset=True)
|
|
4514
|
+
if self.FW["fw_ver"] >= 14 and "set_audio_high" in cart_type:
|
|
4515
|
+
self._set_fw_variable("DMG_AUDIO_ENABLED", 0)
|
|
4428
4516
|
# ↑↑↑ Reset flash
|
|
4429
4517
|
|
|
4430
4518
|
# ↓↓↓ Flash verify
|
|
@@ -4490,8 +4578,6 @@ class LK_Device(ABC):
|
|
|
4490
4578
|
else:
|
|
4491
4579
|
self._write(self.DEVICE_CMD["SET_MODE_DMG"], wait=self.FW["fw_ver"] >= 12)
|
|
4492
4580
|
self._write(self.DEVICE_CMD["DMG_MBC_RESET"], wait=True)
|
|
4493
|
-
# else:
|
|
4494
|
-
# self._write(self.DEVICE_CMD["OFW_GB_FLASH_BANK_1_COMMAND_WRITES"])
|
|
4495
4581
|
self._set_fw_variable("DMG_ROM_BANK", bank)
|
|
4496
4582
|
|
|
4497
4583
|
buffer_len = min(buffer_len, bank_size)
|
|
@@ -4501,7 +4587,6 @@ class LK_Device(ABC):
|
|
|
4501
4587
|
if end_address > start_address + sector[1]:
|
|
4502
4588
|
end_address = start_address + sector[1]
|
|
4503
4589
|
pos_from = (bank * start_address)
|
|
4504
|
-
# pos_to = (bank * start_address) + verify_len
|
|
4505
4590
|
|
|
4506
4591
|
elif self.MODE == "AGB":
|
|
4507
4592
|
if "flash_bank_select_type" in cart_type and cart_type["flash_bank_select_type"] > 0:
|
|
@@ -4514,14 +4599,13 @@ class LK_Device(ABC):
|
|
|
4514
4599
|
current_bank = bank
|
|
4515
4600
|
verify_len = sector[1]
|
|
4516
4601
|
pos_from = sector[0]
|
|
4517
|
-
# pos_to = pos_from + verify_len
|
|
4518
4602
|
# ↑↑↑ Switch ROM bank
|
|
4519
4603
|
|
|
4520
4604
|
dprint(f"Verifying ROM bank #{bank} at 0x{pos_from:x} (physical 0x{start_address:X}, 0x{verify_len:X} bytes)")
|
|
4521
4605
|
|
|
4522
4606
|
verified = False
|
|
4523
4607
|
if self.FW["fw_ver"] >= 12 and sector[1] >= verify_len and crc32_errors < 5:
|
|
4524
|
-
verified = self.CompareCRC32(buffer=data_import, offset=pos_from, length=verify_len, address=start_address, flashcart=flashcart, reset=False)
|
|
4608
|
+
verified = self.CompareCRC32(buffer=data_import, offset=pos_from, length=verify_len, address=start_address, flashcart=flashcart, reset=False, mbc=_mbc, bank=bank)
|
|
4525
4609
|
if verified is True:
|
|
4526
4610
|
dprint("CRC32 verification successful between 0x{:X} and 0x{:X}".format(pos_from, verify_len))
|
|
4527
4611
|
self.SetProgress({"action":"UPDATE_POS", "pos":pos_from + verify_len})
|
|
@@ -4610,9 +4694,10 @@ class LK_Device(ABC):
|
|
|
4610
4694
|
|
|
4611
4695
|
self.SetMode(self.MODE)
|
|
4612
4696
|
|
|
4613
|
-
|
|
4614
|
-
|
|
4615
|
-
|
|
4697
|
+
if not "photo_mode" in args:
|
|
4698
|
+
self.INFO["last_action"] = self.INFO["action"]
|
|
4699
|
+
self.INFO["action"] = None
|
|
4700
|
+
self.SetProgress({"action":"FINISHED", "verified":verified})
|
|
4616
4701
|
return True
|
|
4617
4702
|
|
|
4618
4703
|
#################################################################
|
|
@@ -4639,7 +4724,7 @@ class LK_Device(ABC):
|
|
|
4639
4724
|
self.SIGNAL = signal
|
|
4640
4725
|
try:
|
|
4641
4726
|
temp = copy.copy(args)
|
|
4642
|
-
if "buffer" in temp: temp["buffer"] = "(data)"
|
|
4727
|
+
if "buffer" in temp: temp["buffer"] = "(0x{:x} bytes of data)".format(len(temp["buffer"]))
|
|
4643
4728
|
dprint("args:", temp)
|
|
4644
4729
|
del(temp)
|
|
4645
4730
|
self.NO_PROG_UPDATE = False
|