FlashGBX 3.37__py3-none-any.whl → 4.0__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 +14 -7
- FlashGBX/FlashGBX_CLI.py +201 -24
- FlashGBX/FlashGBX_GUI.py +636 -204
- FlashGBX/Flashcart.py +184 -83
- FlashGBX/GBMemory.py +4 -5
- FlashGBX/LK_Device.py +4526 -0
- FlashGBX/Mapper.py +534 -356
- FlashGBX/RomFileAGB.py +92 -2
- FlashGBX/RomFileDMG.py +1 -1
- FlashGBX/UserInputDialog.py +20 -0
- FlashGBX/Util.py +95 -47
- FlashGBX/fw_GBFlash.py +426 -0
- FlashGBX/fw_GBxCartRW_v1_3.py +1 -1
- FlashGBX/fw_JoeyJr.py +472 -0
- FlashGBX/hw_GBFlash.py +244 -0
- FlashGBX/hw_GBxCartRW.py +200 -3777
- FlashGBX/hw_JoeyJr.py +309 -0
- FlashGBX/res/Third Party Notices.md +342 -0
- FlashGBX/res/config.zip +0 -0
- FlashGBX/res/fw_GBFlash.zip +0 -0
- FlashGBX/res/fw_GBxCart_RW_v1_3.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-3.37.dist-info → FlashGBX-4.0.dist-info}/METADATA +33 -14
- FlashGBX-4.0.dist-info/RECORD +43 -0
- FlashGBX/hw_GBxCartRW_ofw.py +0 -2599
- FlashGBX-3.37.dist-info/RECORD +0 -36
- {FlashGBX-3.37.dist-info → FlashGBX-4.0.dist-info}/LICENSE +0 -0
- {FlashGBX-3.37.dist-info → FlashGBX-4.0.dist-info}/WHEEL +0 -0
- {FlashGBX-3.37.dist-info → FlashGBX-4.0.dist-info}/entry_points.txt +0 -0
- {FlashGBX-3.37.dist-info → FlashGBX-4.0.dist-info}/top_level.txt +0 -0
FlashGBX/Flashcart.py
CHANGED
|
@@ -99,6 +99,13 @@ class Flashcart:
|
|
|
99
99
|
else:
|
|
100
100
|
return ("buffer_write" in self.CONFIG["commands"])
|
|
101
101
|
|
|
102
|
+
def SupportsPageWrite(self):
|
|
103
|
+
buffer_size = self.GetBufferSize()
|
|
104
|
+
if buffer_size is False:
|
|
105
|
+
return False
|
|
106
|
+
else:
|
|
107
|
+
return ("page_write" in self.CONFIG["commands"])
|
|
108
|
+
|
|
102
109
|
def SupportsSingleWrite(self):
|
|
103
110
|
return ("single_write" in self.CONFIG["commands"])
|
|
104
111
|
|
|
@@ -180,17 +187,17 @@ class Flashcart:
|
|
|
180
187
|
if full_reset and "power_cycle" in self.CONFIG:
|
|
181
188
|
self.CART_POWERCYCLE_FNCPTR()
|
|
182
189
|
time.sleep(0.001)
|
|
183
|
-
self.Unlock()
|
|
190
|
+
if self.Unlock() is False: return False
|
|
184
191
|
elif full_reset and "reset_every" in self.CONFIG and "flash_size" in self.CONFIG:
|
|
185
192
|
for j in range(0, self.CONFIG["flash_size"], self.CONFIG["reset_every"]):
|
|
186
193
|
if j >= max_address: break
|
|
187
194
|
dprint("reset_every @ 0x{:X}".format(j))
|
|
188
195
|
for command in self.CONFIG["commands"]["reset"]:
|
|
189
196
|
self.CartWrite([[j + command[0], command[1]]])
|
|
190
|
-
time.sleep(0.01)
|
|
197
|
+
#time.sleep(0.01)
|
|
191
198
|
elif "reset" in self.CONFIG["commands"]:
|
|
192
199
|
self.CartWrite(self.CONFIG["commands"]["reset"])
|
|
193
|
-
time.sleep(0.001)
|
|
200
|
+
#time.sleep(0.001)
|
|
194
201
|
|
|
195
202
|
def _VerifyFlashID(self, config):
|
|
196
203
|
if "read_identifier" not in config["commands"]: return (False, [])
|
|
@@ -238,7 +245,7 @@ class Flashcart:
|
|
|
238
245
|
if self.CFI is not None: return self.CFI
|
|
239
246
|
if "read_cfi" not in self.CONFIG["commands"]:
|
|
240
247
|
if self.CONFIG["_command_set"] == "INTEL":
|
|
241
|
-
self.CONFIG["commands"]["read_cfi"] =
|
|
248
|
+
self.CONFIG["commands"]["read_cfi"] = [ [ 0, 0x98 ] ]
|
|
242
249
|
elif self.CONFIG["_command_set"] == "AMD":
|
|
243
250
|
self.CONFIG["commands"]["read_cfi"] = [ [ 0xAA, 0x98 ] ]
|
|
244
251
|
|
|
@@ -365,82 +372,92 @@ class Flashcart:
|
|
|
365
372
|
self.Reset(full_reset=True)
|
|
366
373
|
return True
|
|
367
374
|
|
|
368
|
-
def SectorErase(self, pos=0, buffer_pos=0):
|
|
369
|
-
|
|
370
|
-
|
|
371
|
-
|
|
372
|
-
|
|
373
|
-
|
|
374
|
-
|
|
375
|
-
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
if addr == "SA+1": addr = pos + 1
|
|
382
|
-
if addr == "SA+2": addr = pos + 2
|
|
383
|
-
if addr == "SA+0x4000": addr = pos + 0x4000
|
|
384
|
-
if addr == "SA+0x7000": addr = pos + 0x7000
|
|
385
|
-
if not addr == None:
|
|
386
|
-
if we == "WR":
|
|
387
|
-
self.SET_WE_PIN_WR()
|
|
388
|
-
elif we == "AUDIO":
|
|
389
|
-
self.SET_WE_PIN_AUDIO()
|
|
390
|
-
self.CartWrite([[addr, data]])
|
|
391
|
-
if we is not None:
|
|
392
|
-
if self.DEFAULT_WE == "WR":
|
|
393
|
-
self.SET_WE_PIN_WR()
|
|
394
|
-
elif self.DEFAULT_WE == "AUDIO":
|
|
395
|
-
self.SET_WE_PIN_AUDIO()
|
|
396
|
-
|
|
397
|
-
if self.CONFIG["commands"]["sector_erase_wait_for"][i][0] != None:
|
|
398
|
-
addr = self.CONFIG["commands"]["sector_erase_wait_for"][i][0]
|
|
399
|
-
data = self.CONFIG["commands"]["sector_erase_wait_for"][i][1]
|
|
375
|
+
def SectorErase(self, pos=0, buffer_pos=0, skip=False):
|
|
376
|
+
if not skip:
|
|
377
|
+
self.Reset(full_reset=False)
|
|
378
|
+
if "sector_erase" not in self.CONFIG["commands"]: return False
|
|
379
|
+
if "sector_size" not in self.CONFIG: return False
|
|
380
|
+
for i in range(0, len(self.CONFIG["commands"]["sector_erase"])):
|
|
381
|
+
addr = self.CONFIG["commands"]["sector_erase"][i][0]
|
|
382
|
+
data = self.CONFIG["commands"]["sector_erase"][i][1]
|
|
383
|
+
if len(self.CONFIG["commands"]["sector_erase"][i]) > 2:
|
|
384
|
+
we = self.CONFIG["commands"]["sector_erase"][i][2]
|
|
385
|
+
else:
|
|
386
|
+
we = None
|
|
387
|
+
|
|
400
388
|
if addr == "SA": addr = pos
|
|
401
389
|
if addr == "SA+1": addr = pos + 1
|
|
402
390
|
if addr == "SA+2": addr = pos + 2
|
|
403
|
-
if addr == "SA+
|
|
404
|
-
if addr == "SA+
|
|
405
|
-
|
|
406
|
-
|
|
407
|
-
|
|
408
|
-
if
|
|
409
|
-
|
|
410
|
-
|
|
411
|
-
|
|
391
|
+
if addr == "SA+16384": addr = pos + 0x4000
|
|
392
|
+
if addr == "SA+28672": addr = pos + 0x7000
|
|
393
|
+
if addr == "SA+66": addr = pos + 0x42
|
|
394
|
+
if addr == "SA+132": addr = pos + 0x84
|
|
395
|
+
if not addr == None:
|
|
396
|
+
if we == "WR":
|
|
397
|
+
self.SET_WE_PIN_WR()
|
|
398
|
+
elif we == "AUDIO":
|
|
399
|
+
self.SET_WE_PIN_AUDIO()
|
|
400
|
+
self.CartWrite([[addr, data]])
|
|
401
|
+
if we is not None:
|
|
402
|
+
if self.DEFAULT_WE == "WR":
|
|
403
|
+
self.SET_WE_PIN_WR()
|
|
404
|
+
elif self.DEFAULT_WE == "AUDIO":
|
|
405
|
+
self.SET_WE_PIN_AUDIO()
|
|
406
|
+
|
|
407
|
+
if self.CONFIG["commands"]["sector_erase_wait_for"][i][0] != None:
|
|
408
|
+
addr = self.CONFIG["commands"]["sector_erase_wait_for"][i][0]
|
|
409
|
+
data = self.CONFIG["commands"]["sector_erase_wait_for"][i][1]
|
|
410
|
+
if addr == "SA": addr = pos
|
|
411
|
+
if addr == "SA+1": addr = pos + 1
|
|
412
|
+
if addr == "SA+2": addr = pos + 2
|
|
413
|
+
if addr == "SA+16384": addr = pos + 0x4000
|
|
414
|
+
if addr == "SA+28672": addr = pos + 0x7000
|
|
415
|
+
if addr == "SA+66": addr = pos + 0x42
|
|
416
|
+
if addr == "SA+132": addr = pos + 0x84
|
|
417
|
+
time.sleep(0.05)
|
|
418
|
+
timeout = 100
|
|
419
|
+
while True:
|
|
420
|
+
if "wait_read_status_register" in self.CONFIG and self.CONFIG["wait_read_status_register"] == True:
|
|
421
|
+
for j in range(0, len(self.CONFIG["commands"]["read_status_register"])):
|
|
422
|
+
sr_addr = self.CONFIG["commands"]["read_status_register"][j][0]
|
|
423
|
+
sr_data = self.CONFIG["commands"]["read_status_register"][j][1]
|
|
412
424
|
|
|
413
|
-
|
|
414
|
-
self.SET_WE_PIN_WR()
|
|
415
|
-
elif we == "AUDIO":
|
|
416
|
-
self.SET_WE_PIN_AUDIO()
|
|
417
|
-
self.CartWrite([[sr_addr, sr_data]])
|
|
418
|
-
if we is not None:
|
|
419
|
-
if self.DEFAULT_WE == "WR":
|
|
425
|
+
if we == "WR":
|
|
420
426
|
self.SET_WE_PIN_WR()
|
|
421
|
-
elif
|
|
427
|
+
elif we == "AUDIO":
|
|
422
428
|
self.SET_WE_PIN_AUDIO()
|
|
423
|
-
|
|
424
|
-
|
|
425
|
-
|
|
426
|
-
|
|
427
|
-
|
|
428
|
-
|
|
429
|
-
|
|
430
|
-
|
|
431
|
-
|
|
432
|
-
|
|
433
|
-
|
|
434
|
-
|
|
435
|
-
|
|
436
|
-
|
|
437
|
-
|
|
438
|
-
|
|
439
|
-
|
|
440
|
-
|
|
441
|
-
|
|
429
|
+
self.CartWrite([[sr_addr, sr_data]])
|
|
430
|
+
if we is not None:
|
|
431
|
+
if self.DEFAULT_WE == "WR":
|
|
432
|
+
self.SET_WE_PIN_WR()
|
|
433
|
+
elif self.DEFAULT_WE == "AUDIO":
|
|
434
|
+
self.SET_WE_PIN_AUDIO()
|
|
435
|
+
|
|
436
|
+
self.CartRead(addr, 2) # dummy read (fixes some bootlegs)
|
|
437
|
+
temp = self.CartRead(addr, 2)
|
|
438
|
+
if len(temp) != 2:
|
|
439
|
+
dprint("Communication error 1 in SectorErase():", temp)
|
|
440
|
+
return False
|
|
441
|
+
wait_for = self.CartRead(addr, 2)
|
|
442
|
+
if len(wait_for) != 2:
|
|
443
|
+
dprint("Communication error 2 in SectorErase():", temp)
|
|
444
|
+
return False
|
|
445
|
+
wait_for = struct.unpack("<H", wait_for)[0]
|
|
446
|
+
self.LAST_SR = wait_for
|
|
447
|
+
dprint("Status Register Check: 0x{:X} & 0x{:X} == 0x{:X}? {:s}".format(wait_for, self.CONFIG["commands"]["sector_erase_wait_for"][i][2], data, str(wait_for & self.CONFIG["commands"]["sector_erase_wait_for"][i][2] == data)))
|
|
448
|
+
wait_for = wait_for & self.CONFIG["commands"]["sector_erase_wait_for"][i][2]
|
|
449
|
+
time.sleep(0.05)
|
|
450
|
+
timeout -= 1
|
|
451
|
+
if timeout < 1:
|
|
452
|
+
dprint(f"Timeout error in SectorErase(): 0x{self.LAST_SR:X}")
|
|
453
|
+
#self.PROGRESS_FNCPTR({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"The sector erase attempt timed out. The last status register value was 0x{:X}.\n\nPlease make sure that the cartridge contacts are clean, and that the selected cartridge type and settings are correct.".format(self.LAST_SR), "abortable":False})
|
|
454
|
+
return False
|
|
455
|
+
if wait_for == data: break
|
|
456
|
+
self.PROGRESS_FNCPTR({"action":"SECTOR_ERASE", "sector_pos":buffer_pos, "time_start":time.time(), "abortable":True})
|
|
457
|
+
dprint("Done waiting!")
|
|
442
458
|
|
|
443
|
-
|
|
459
|
+
self.Reset(full_reset=False)
|
|
460
|
+
|
|
444
461
|
if isinstance(self.CONFIG["sector_size"], list):
|
|
445
462
|
self.CONFIG["sector_size"][self.SECTOR_POS][1] -= 1
|
|
446
463
|
if (self.CONFIG["sector_size"][self.SECTOR_POS][1] == 0) and (len(self.CONFIG["sector_size"]) > self.SECTOR_POS + 1):
|
|
@@ -488,16 +505,18 @@ class CFI:
|
|
|
488
505
|
magic = "{:s}{:s}{:s}".format(chr(buffer[0x20]), chr(buffer[0x22]), chr(buffer[0x24]))
|
|
489
506
|
info["d_swap"] = None
|
|
490
507
|
if magic == "QRY": # nothing swapped
|
|
491
|
-
info["d_swap"] = ( 0, 0 )
|
|
508
|
+
info["d_swap"] = [( 0, 0 )]
|
|
492
509
|
elif magic == "RQZ": # D0D1 swapped
|
|
493
|
-
info["d_swap"] = ( 0, 1 )
|
|
510
|
+
info["d_swap"] = [( 0, 1 )]
|
|
511
|
+
elif magic == "\x92\x91\x9A": # D0D1+D6D7 swapped
|
|
512
|
+
info["d_swap"] = [( 0, 1 ), ( 6, 7 )]
|
|
494
513
|
else:
|
|
495
514
|
return False
|
|
496
515
|
|
|
497
516
|
if info["d_swap"] is not None:
|
|
498
|
-
for
|
|
499
|
-
|
|
500
|
-
|
|
517
|
+
for j2 in range(0, len(info["d_swap"])):
|
|
518
|
+
for j in range(0, len(buffer)):
|
|
519
|
+
buffer[j] = bitswap(buffer[j], info["d_swap"][j2])
|
|
501
520
|
try:
|
|
502
521
|
info["flash_id"] = buffer[0:8]
|
|
503
522
|
info["magic"] = "{:s}{:s}{:s}".format(chr(buffer[0x20]), chr(buffer[0x22]), chr(buffer[0x24]))
|
|
@@ -586,7 +605,7 @@ class CFI:
|
|
|
586
605
|
return False
|
|
587
606
|
|
|
588
607
|
s = ""
|
|
589
|
-
if info["d_swap"] is not None and info["d_swap"] != ( 0, 0 ): s += "Swapped pins: {:s}\n".format(str(info["d_swap"]))
|
|
608
|
+
if info["d_swap"] is not None and info["d_swap"] != [( 0, 0 )]: s += "Swapped pins: {:s}\n".format(str(info["d_swap"]))
|
|
590
609
|
s += "Device size: 0x{:07X} ({:.2f} MB)\n".format(info["device_size"], info["device_size"] / 1024 / 1024)
|
|
591
610
|
s += "Voltage: {:.1f}–{:.1f} V\n".format(info["vdd_min"], info["vdd_max"])
|
|
592
611
|
s += "Single write: {:s}\n".format(str(info["single_write"]))
|
|
@@ -612,6 +631,88 @@ class CFI:
|
|
|
612
631
|
|
|
613
632
|
return info
|
|
614
633
|
|
|
634
|
+
class Flashcart_AGB_GBAMP(Flashcart):
|
|
635
|
+
def SectorErase(self, pos=0, buffer_pos=0, skip=False):
|
|
636
|
+
for i in range(0, 4):
|
|
637
|
+
sector = pos >> 13 << 16 | (pos & 0x1FFF) + (i * 4)
|
|
638
|
+
ret = super().SectorErase(sector, buffer_pos, skip)
|
|
639
|
+
if ret is False: break
|
|
640
|
+
return ret
|
|
641
|
+
|
|
642
|
+
def VerifyFlashID(self):
|
|
643
|
+
self.CART_POWERCYCLE_FNCPTR()
|
|
644
|
+
verified = False
|
|
645
|
+
self.Unlock()
|
|
646
|
+
rom = list(self.CartRead(0x1E8F << 1, 2) + self.CartRead(0x168F << 1, 2))
|
|
647
|
+
self.CartWrite(self.CONFIG["commands"]["read_identifier"], fast_write=True)
|
|
648
|
+
cart_flash_id = list(self.CartRead(0x1E8F << 1, 2) + self.CartRead(0x168F << 1, 2))
|
|
649
|
+
if rom != cart_flash_id and cart_flash_id == self.CONFIG["flash_ids"][0]:
|
|
650
|
+
self.CartWrite(self.CONFIG["commands"]["reset"], fast_write=True)
|
|
651
|
+
verified = True
|
|
652
|
+
dprint(verified, rom, cart_flash_id)
|
|
653
|
+
return (verified, cart_flash_id)
|
|
654
|
+
|
|
655
|
+
class Flashcart_DMG_BUNG_16M(Flashcart):
|
|
656
|
+
def SupportsSectorErase(self):
|
|
657
|
+
return False
|
|
658
|
+
|
|
659
|
+
def SupportsChipErase(self):
|
|
660
|
+
return True
|
|
661
|
+
|
|
662
|
+
def ChipErase(self, pos=0, buffer_pos=0, skip=False):
|
|
663
|
+
time_start = time.time()
|
|
664
|
+
if self.PROGRESS_FNCPTR is not None: self.PROGRESS_FNCPTR({"action":"ERASE", "time_start":time_start, "abortable":False})
|
|
665
|
+
|
|
666
|
+
self.CartWrite([[0x2000, 0x02]], fast_write=False)
|
|
667
|
+
self.CartWrite([[0x6AAA, 0xAA]], fast_write=True)
|
|
668
|
+
self.CartWrite([[0x2000, 0x01]], fast_write=False)
|
|
669
|
+
self.CartWrite([[0x5554, 0x55]], fast_write=True)
|
|
670
|
+
self.CartWrite([[0x2000, 0x02]], fast_write=False)
|
|
671
|
+
self.CartWrite([[0x6AAA, 0x80]], fast_write=True)
|
|
672
|
+
self.CartWrite([[0x2000, 0x02]], fast_write=False)
|
|
673
|
+
self.CartWrite([[0x6AAA, 0xAA]], fast_write=True)
|
|
674
|
+
self.CartWrite([[0x2000, 0x01]], fast_write=False)
|
|
675
|
+
self.CartWrite([[0x5554, 0x55]], fast_write=True)
|
|
676
|
+
self.CartWrite([[0x2000, 0x02]], fast_write=False)
|
|
677
|
+
self.CartWrite([[0x6AAA, 0x10]], fast_write=True)
|
|
678
|
+
|
|
679
|
+
lives = 10
|
|
680
|
+
while lives > 0:
|
|
681
|
+
sr = ord(self.CartRead(0))
|
|
682
|
+
self.LAST_SR = sr
|
|
683
|
+
dprint("Status Register Check: 0x{:X} & 0x{:X} == 0x{:X}? {:s}".format(sr, 0x80, 0x80, str((sr & 0x80) == 0x80)))
|
|
684
|
+
if (sr & 0x80) == 0x80: break
|
|
685
|
+
time.sleep(0.5)
|
|
686
|
+
lives -= 1
|
|
687
|
+
if lives == 0:
|
|
688
|
+
self.PROGRESS_FNCPTR({"action":"ABORT", "info_type":"msgbox_critical", "info_msg":"Erasing the flash chip timed out. The last status register value was 0x{:X}.\n\nPlease make sure that the cartridge contacts are clean, and that the selected cartridge type and settings are correct.".format(self.LAST_SR), "abortable":False})
|
|
689
|
+
return False
|
|
690
|
+
|
|
691
|
+
self.Reset()
|
|
692
|
+
return True
|
|
693
|
+
|
|
694
|
+
def Reset(self, full_reset=None, max_address=None):
|
|
695
|
+
self.CartWrite([[0x2000, 0x02]], fast_write=False)
|
|
696
|
+
self.CartWrite([[0x6AAA, 0xAA]], fast_write=True)
|
|
697
|
+
self.CartWrite([[0x2000, 0x01]], fast_write=False)
|
|
698
|
+
self.CartWrite([[0x5554, 0x55]], fast_write=True)
|
|
699
|
+
self.CartWrite([[0x2000, 0x02]], fast_write=False)
|
|
700
|
+
self.CartWrite([[0x6AAA, 0xF0]], fast_write=True)
|
|
701
|
+
|
|
702
|
+
def VerifyFlashID(self):
|
|
703
|
+
rom = list(self.CartRead(0, 4))
|
|
704
|
+
self.CartWrite([[0x2000, 0x02]], fast_write=False)
|
|
705
|
+
self.CartWrite([[0x6AAA, 0xAA]], fast_write=True)
|
|
706
|
+
self.CartWrite([[0x2000, 0x01]], fast_write=False)
|
|
707
|
+
self.CartWrite([[0x5554, 0x55]], fast_write=True)
|
|
708
|
+
self.CartWrite([[0x2000, 0x02]], fast_write=False)
|
|
709
|
+
self.CartWrite([[0x6AAA, 0x90]], fast_write=True)
|
|
710
|
+
cart_flash_id = list(self.CartRead(0, 4))
|
|
711
|
+
if rom != cart_flash_id and cart_flash_id == self.CONFIG["flash_ids"][0]:
|
|
712
|
+
self.Reset()
|
|
713
|
+
verified = True
|
|
714
|
+
return (verified, cart_flash_id)
|
|
715
|
+
|
|
615
716
|
class Flashcart_DMG_MMSA(Flashcart):
|
|
616
717
|
def ReadCFI(self):
|
|
617
718
|
return False
|
|
@@ -628,7 +729,7 @@ class Flashcart_DMG_MMSA(Flashcart):
|
|
|
628
729
|
def EraseHiddenSector(self, buffer):
|
|
629
730
|
if self.PROGRESS_FNCPTR is not None: self.PROGRESS_FNCPTR({"action":"SECTOR_ERASE", "sector_pos":0, "time_start":time.time(), "abortable":False})
|
|
630
731
|
|
|
631
|
-
self.UnlockForWriting()
|
|
732
|
+
if self.UnlockForWriting() is False: return False
|
|
632
733
|
|
|
633
734
|
cmds = [
|
|
634
735
|
[ 0x120, 0x0F ],
|
|
@@ -748,13 +849,13 @@ class Flashcart_DMG_MMSA(Flashcart):
|
|
|
748
849
|
# Disable writes to MBC registers
|
|
749
850
|
cmds = [
|
|
750
851
|
[ 0x120, 0x10 ],
|
|
751
|
-
[ 0x13F,
|
|
852
|
+
[ 0x13F, 0xA5 ],
|
|
752
853
|
]
|
|
753
854
|
self.CartWrite(cmds)
|
|
754
855
|
# Undo Wakeup
|
|
755
856
|
cmds = [
|
|
756
857
|
[ 0x120, 0x08 ],
|
|
757
|
-
[ 0x13F,
|
|
858
|
+
[ 0x13F, 0xA5 ],
|
|
758
859
|
]
|
|
759
860
|
self.CartWrite(cmds)
|
|
760
861
|
return True
|
|
@@ -763,7 +864,7 @@ class Flashcart_DMG_MMSA(Flashcart):
|
|
|
763
864
|
time_start = time.time()
|
|
764
865
|
if self.PROGRESS_FNCPTR is not None: self.PROGRESS_FNCPTR({"action":"ERASE", "time_start":time_start, "abortable":False})
|
|
765
866
|
|
|
766
|
-
self.UnlockForWriting()
|
|
867
|
+
if self.UnlockForWriting() is False: return False
|
|
767
868
|
|
|
768
869
|
# Erase Chip
|
|
769
870
|
cmds = [
|
FlashGBX/GBMemory.py
CHANGED
|
@@ -11,10 +11,9 @@ class GBMemoryMap:
|
|
|
11
11
|
IS_MENU = False
|
|
12
12
|
|
|
13
13
|
def __init__(self, rom=None, oldmap=None):
|
|
14
|
+
self.MAP_DATA = bytearray([0xFF] * 0x80)
|
|
14
15
|
if rom is None: return
|
|
15
|
-
if rom
|
|
16
|
-
self.MAP_DATA = bytearray([0x00] * 0x80)
|
|
17
|
-
elif rom is not None:
|
|
16
|
+
if rom is not None:
|
|
18
17
|
self.ImportROM(rom)
|
|
19
18
|
if oldmap is not None:
|
|
20
19
|
self.MAP_DATA[0x70:0x78] = oldmap[0x70:0x78] # keep existing cart id
|
|
@@ -316,6 +315,6 @@ class GBMemoryMap:
|
|
|
316
315
|
return self.IS_MENU
|
|
317
316
|
|
|
318
317
|
def GetMapData(self):
|
|
319
|
-
if self.MAP_DATA == bytearray([0xFF] * 0x80):
|
|
320
|
-
|
|
318
|
+
#if self.MAP_DATA == bytearray([0xFF] * 0x80):
|
|
319
|
+
# return False
|
|
321
320
|
return self.MAP_DATA
|