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/Mapper.py
CHANGED
|
@@ -18,7 +18,7 @@ class DMG_MBC:
|
|
|
18
18
|
RAM_BANK_SIZE = 0x2000
|
|
19
19
|
ROM_BANK_NUM = 0
|
|
20
20
|
CURRENT_ROM_BANK = 0
|
|
21
|
-
CURRENT_FLASH_BANK =
|
|
21
|
+
CURRENT_FLASH_BANK = -1
|
|
22
22
|
START_BANK = 0
|
|
23
23
|
RTC_BUFFER = None
|
|
24
24
|
|
|
@@ -195,6 +195,12 @@ class DMG_MBC:
|
|
|
195
195
|
def WriteRTC(self, buffer, advance=False):
|
|
196
196
|
pass
|
|
197
197
|
|
|
198
|
+
def GetRTCDict(self):
|
|
199
|
+
return {}
|
|
200
|
+
|
|
201
|
+
def WriteRTCDict(self, rtc_dict):
|
|
202
|
+
pass
|
|
203
|
+
|
|
198
204
|
def GetRTCString(self):
|
|
199
205
|
return "Not available"
|
|
200
206
|
|
|
@@ -294,12 +300,10 @@ class DMG_MBC3(DMG_MBC):
|
|
|
294
300
|
dprint("Latching RTC")
|
|
295
301
|
self.CLK_TOGGLE_FNCPTR(60)
|
|
296
302
|
self.CartWrite([ [ 0x0000, 0x0A ] ])
|
|
297
|
-
time.sleep(0.01)
|
|
298
303
|
self.CLK_TOGGLE_FNCPTR(60)
|
|
299
304
|
self.CartWrite([ [ 0x6000, 0x00 ] ])
|
|
300
305
|
self.CLK_TOGGLE_FNCPTR(60)
|
|
301
306
|
self.CartWrite([ [ 0x6000, 0x01 ] ])
|
|
302
|
-
time.sleep(0.01)
|
|
303
307
|
|
|
304
308
|
def ReadRTC(self):
|
|
305
309
|
dprint("Reading RTC")
|
|
@@ -320,7 +324,53 @@ class DMG_MBC3(DMG_MBC):
|
|
|
320
324
|
self.CartWrite([ [0x4000, 0] ])
|
|
321
325
|
self.RTC_BUFFER = buffer
|
|
322
326
|
return buffer
|
|
327
|
+
|
|
328
|
+
def WriteRTCDict(self, rtc_dict):
|
|
329
|
+
dprint("Writing RTC:", rtc_dict)
|
|
330
|
+
self.EnableRAM(enable=True)
|
|
331
|
+
|
|
332
|
+
buffer = bytearray(5)
|
|
333
|
+
buffer[0] = rtc_dict["rtc_s"] % 60
|
|
334
|
+
buffer[1] = rtc_dict["rtc_m"] % 60
|
|
335
|
+
buffer[2] = rtc_dict["rtc_h"] % 24
|
|
336
|
+
buffer[3] = rtc_dict["rtc_d"] & 0xFF
|
|
337
|
+
buffer[4] = rtc_dict["rtc_d"] >> 8 & 1
|
|
338
|
+
|
|
339
|
+
dprint("New values: RTC_S=0x{:02X}, RTC_M=0x{:02X}, RTC_H=0x{:02X}, RTC_DL=0x{:02X}, RTC_DH=0x{:02X}".format(buffer[0], buffer[1], buffer[2], buffer[3], buffer[4]))
|
|
340
|
+
|
|
341
|
+
# Unlock and latch RTC
|
|
342
|
+
self.CLK_TOGGLE_FNCPTR(50)
|
|
343
|
+
self.CartWrite([ [ 0x0000, 0x0A ] ])
|
|
344
|
+
self.CLK_TOGGLE_FNCPTR(50)
|
|
345
|
+
self.CartWrite([ [ 0x6000, 0x00 ] ])
|
|
346
|
+
self.CLK_TOGGLE_FNCPTR(50)
|
|
347
|
+
self.CartWrite([ [ 0x6000, 0x01 ] ])
|
|
323
348
|
|
|
349
|
+
# Halt RTC
|
|
350
|
+
self.CLK_TOGGLE_FNCPTR(50)
|
|
351
|
+
self.CartWrite([ [ 0x4000, 0x0C ] ])
|
|
352
|
+
self.CLK_TOGGLE_FNCPTR(50)
|
|
353
|
+
self.CartWrite([ [ 0xA000, 0x40 ] ], sram=True)
|
|
354
|
+
|
|
355
|
+
# Write to registers
|
|
356
|
+
for i in range(0x08, 0x0D):
|
|
357
|
+
self.CLK_TOGGLE_FNCPTR(50)
|
|
358
|
+
self.CartWrite([ [ 0x4000, i ] ])
|
|
359
|
+
self.CLK_TOGGLE_FNCPTR(50)
|
|
360
|
+
data = buffer[i-8]
|
|
361
|
+
self.CartWrite([ [ 0xA000, data ] ], sram=True)
|
|
362
|
+
|
|
363
|
+
# Latch RTC
|
|
364
|
+
self.CLK_TOGGLE_FNCPTR(50)
|
|
365
|
+
self.CartWrite([ [ 0x6000, 0x00 ] ])
|
|
366
|
+
self.CLK_TOGGLE_FNCPTR(50)
|
|
367
|
+
self.CartWrite([ [ 0x6000, 0x01 ] ])
|
|
368
|
+
|
|
369
|
+
self.CartWrite([ [0x4000, 0] ])
|
|
370
|
+
self.EnableRAM(enable=False)
|
|
371
|
+
|
|
372
|
+
return True
|
|
373
|
+
|
|
324
374
|
def WriteRTC(self, buffer, advance=False):
|
|
325
375
|
dprint("Writing RTC:", buffer)
|
|
326
376
|
self.EnableRAM(enable=True)
|
|
@@ -363,55 +413,26 @@ class DMG_MBC3(DMG_MBC):
|
|
|
363
413
|
days = days % 512
|
|
364
414
|
dprint(seconds, minutes, hours, days, carry)
|
|
365
415
|
|
|
366
|
-
buffer[0x00] = seconds % 60
|
|
367
|
-
buffer[0x04] = minutes % 60
|
|
368
|
-
buffer[0x08] = hours % 24
|
|
369
|
-
buffer[0x0C] = days & 0xFF
|
|
370
|
-
buffer[0x10] = days >> 8 & 0x1
|
|
371
|
-
if carry:
|
|
372
|
-
|
|
416
|
+
#buffer[0x00] = seconds % 60
|
|
417
|
+
#buffer[0x04] = minutes % 60
|
|
418
|
+
#buffer[0x08] = hours % 24
|
|
419
|
+
#buffer[0x0C] = days & 0xFF
|
|
420
|
+
#buffer[0x10] = days >> 8 & 0x1
|
|
421
|
+
#if carry:
|
|
422
|
+
# buffer[0x10] |= 0x80
|
|
373
423
|
except Exception as e:
|
|
374
424
|
print("Couldn’t update the RTC register values\n", e)
|
|
375
425
|
|
|
376
|
-
|
|
377
|
-
|
|
378
|
-
|
|
379
|
-
|
|
380
|
-
|
|
381
|
-
|
|
382
|
-
self.
|
|
383
|
-
self.CLK_TOGGLE_FNCPTR(50)
|
|
384
|
-
self.CartWrite([ [ 0x6000, 0x01 ] ])
|
|
385
|
-
time.sleep(0.01)
|
|
386
|
-
|
|
387
|
-
# Halt RTC
|
|
388
|
-
self.CLK_TOGGLE_FNCPTR(50)
|
|
389
|
-
self.CartWrite([ [ 0x4000, 0x0C ] ])
|
|
390
|
-
self.CLK_TOGGLE_FNCPTR(50)
|
|
391
|
-
self.CartWrite([ [ 0xA000, 0x40 ] ], sram=True)
|
|
392
|
-
time.sleep(0.1)
|
|
393
|
-
|
|
394
|
-
# Write to registers
|
|
395
|
-
for i in range(0x08, 0x0D):
|
|
396
|
-
self.CLK_TOGGLE_FNCPTR(50)
|
|
397
|
-
self.CartWrite([ [ 0x4000, i ] ])
|
|
398
|
-
self.CLK_TOGGLE_FNCPTR(50)
|
|
399
|
-
data = struct.unpack("<I", buffer[(i-8)*4:(i-8)*4+4])[0] & 0xFF
|
|
400
|
-
self.CartWrite([ [ 0xA000, data ] ], sram=True)
|
|
401
|
-
time.sleep(0.1)
|
|
402
|
-
|
|
403
|
-
# Latch RTC
|
|
404
|
-
self.CLK_TOGGLE_FNCPTR(50)
|
|
405
|
-
self.CartWrite([ [ 0x6000, 0x00 ] ])
|
|
406
|
-
self.CLK_TOGGLE_FNCPTR(50)
|
|
407
|
-
self.CartWrite([ [ 0x6000, 0x01 ] ])
|
|
408
|
-
time.sleep(0.1)
|
|
409
|
-
|
|
410
|
-
self.CartWrite([ [0x4000, 0] ])
|
|
426
|
+
d = {
|
|
427
|
+
"rtc_s":seconds % 60,
|
|
428
|
+
"rtc_m":minutes % 60,
|
|
429
|
+
"rtc_h":hours % 24,
|
|
430
|
+
"rtc_d":days % 512,
|
|
431
|
+
}
|
|
432
|
+
self.WriteRTCDict(d)
|
|
411
433
|
self.EnableRAM(enable=False)
|
|
412
434
|
|
|
413
|
-
def
|
|
414
|
-
s = ""
|
|
435
|
+
def GetRTCDict(self):
|
|
415
436
|
if self.RTC_BUFFER is None:
|
|
416
437
|
self.ReadRTC()
|
|
417
438
|
rtc_buffer = self.RTC_BUFFER
|
|
@@ -421,21 +442,37 @@ class DMG_MBC3(DMG_MBC):
|
|
|
421
442
|
rtc_h = rtc_buffer[0x08]
|
|
422
443
|
rtc_d = (rtc_buffer[0x0C] | rtc_buffer[0x10] << 8) & 0x1FF
|
|
423
444
|
rtc_carry = ((rtc_buffer[0x10] & 0x80) != 0)
|
|
424
|
-
|
|
445
|
+
d = {
|
|
446
|
+
"rtc_d":rtc_d,
|
|
447
|
+
"rtc_h":rtc_h,
|
|
448
|
+
"rtc_m":rtc_m,
|
|
449
|
+
"rtc_s":rtc_s,
|
|
450
|
+
"rtc_carry":rtc_carry
|
|
451
|
+
}
|
|
452
|
+
|
|
453
|
+
#if rtc_carry: rtc_d += 256
|
|
425
454
|
if rtc_h > 24 or rtc_m > 60 or rtc_s > 60:
|
|
426
455
|
try:
|
|
427
456
|
dprint("Invalid RTC state: {:d} days, {:02d}:{:02d}:{:02d}".format(rtc_d, rtc_h, rtc_m, rtc_s))
|
|
428
457
|
except:
|
|
429
458
|
pass
|
|
430
459
|
s = "Invalid state"
|
|
460
|
+
d["rtc_valid"] = False
|
|
431
461
|
elif rtc_h == 0 and rtc_m == 0 and rtc_s == 0 and rtc_d == 0 and rtc_carry == 0:
|
|
432
462
|
s = "Not available"
|
|
463
|
+
d["rtc_valid"] = False
|
|
433
464
|
else:
|
|
434
465
|
if rtc_d == 1:
|
|
435
466
|
s = "{:d} day, {:02d}:{:02d}:{:02d}".format(rtc_d, rtc_h, rtc_m, rtc_s)
|
|
436
467
|
else:
|
|
437
468
|
s = "{:d} days, {:02d}:{:02d}:{:02d}".format(rtc_d, rtc_h, rtc_m, rtc_s)
|
|
438
|
-
|
|
469
|
+
d["rtc_valid"] = True
|
|
470
|
+
|
|
471
|
+
d["string"] = s
|
|
472
|
+
return d
|
|
473
|
+
|
|
474
|
+
def GetRTCString(self):
|
|
475
|
+
return self.GetRTCDict()["string"]
|
|
439
476
|
|
|
440
477
|
def GetMaxROMSize(self):
|
|
441
478
|
return 4*1024*1024
|
|
@@ -460,11 +497,13 @@ class DMG_MBC5(DMG_MBC):
|
|
|
460
497
|
|
|
461
498
|
def SelectBankROM(self, index):
|
|
462
499
|
dprint(self.GetName(), "|", index)
|
|
500
|
+
|
|
501
|
+
self.CURRENT_ROM_BANK = index
|
|
463
502
|
commands = [
|
|
464
503
|
[ 0x3000, ((index >> 8) & 0xFF) ],
|
|
465
504
|
[ 0x2100, index & 0xFF ],
|
|
466
505
|
]
|
|
467
|
-
|
|
506
|
+
|
|
468
507
|
start_address = 0 if index == 0 else 0x4000
|
|
469
508
|
|
|
470
509
|
self.CartWrite(commands)
|
|
@@ -675,7 +714,7 @@ class DMG_GBD(DMG_MBC5):
|
|
|
675
714
|
def SelectBankROM(self, index):
|
|
676
715
|
dprint(self.GetName(), "|", index)
|
|
677
716
|
commands = [
|
|
678
|
-
[
|
|
717
|
+
[ 0x2000, index & 0xFF ],
|
|
679
718
|
]
|
|
680
719
|
|
|
681
720
|
start_address = 0 if index == 0 else 0x4000
|
|
@@ -690,43 +729,78 @@ class DMG_GMMC1(DMG_MBC5):
|
|
|
690
729
|
def GetName(self):
|
|
691
730
|
return "G-MMC1"
|
|
692
731
|
|
|
693
|
-
def
|
|
694
|
-
dprint(self.GetName())
|
|
732
|
+
def lk_dmg_mmsa_flash_command(self, addr, data):
|
|
695
733
|
commands = [
|
|
696
|
-
|
|
697
|
-
[
|
|
698
|
-
[
|
|
699
|
-
[
|
|
700
|
-
[
|
|
701
|
-
|
|
702
|
-
|
|
703
|
-
|
|
704
|
-
|
|
705
|
-
[
|
|
734
|
+
[0x120, 0x0F],
|
|
735
|
+
[0x125, addr >> 8],
|
|
736
|
+
[0x126, addr & 0xFF],
|
|
737
|
+
[0x127, data],
|
|
738
|
+
[0x13F, 0xA5]
|
|
739
|
+
]
|
|
740
|
+
return commands
|
|
741
|
+
def lk_dmg_mmsa_access_mapper(self):
|
|
742
|
+
commands = [
|
|
743
|
+
[0x120, 0x09],
|
|
744
|
+
[0x121, 0xAA],
|
|
745
|
+
[0x122, 0x55],
|
|
746
|
+
[0x13F, 0xA5]
|
|
747
|
+
]
|
|
748
|
+
return commands
|
|
749
|
+
def lk_dmg_mmsa_access_rom(self):
|
|
750
|
+
commands = [
|
|
751
|
+
[0x120, 0x08],
|
|
752
|
+
[0x13F, 0xA5]
|
|
753
|
+
]
|
|
754
|
+
return commands
|
|
755
|
+
def lk_dmg_mmsa_access_mbc(self, enable):
|
|
756
|
+
if enable:
|
|
757
|
+
commands = [
|
|
758
|
+
[0x120, 0x11],
|
|
759
|
+
[0x13F, 0xA5]
|
|
760
|
+
]
|
|
761
|
+
else:
|
|
762
|
+
commands = [
|
|
763
|
+
[0x120, 0x10],
|
|
764
|
+
[0x13F, 0xA5]
|
|
765
|
+
]
|
|
766
|
+
return commands
|
|
767
|
+
def lk_dmg_mmsa_disable_flash_write_protect(self):
|
|
768
|
+
commands = [
|
|
769
|
+
[0x120, 0x0A],
|
|
770
|
+
[0x125, 0x62],
|
|
771
|
+
[0x126, 0x04],
|
|
772
|
+
[0x13F, 0xA5],
|
|
706
773
|
|
|
707
|
-
[
|
|
708
|
-
[
|
|
709
|
-
|
|
710
|
-
# Reset
|
|
711
|
-
[ 0x120, 0x0F ],
|
|
712
|
-
[ 0x125, 0x40 ],
|
|
713
|
-
[ 0x126, 0x80 ],
|
|
714
|
-
[ 0x127, 0xF0 ],
|
|
715
|
-
[ 0x13F, 0xA5 ],
|
|
716
|
-
|
|
717
|
-
[ 0x120, 0x04 ],
|
|
718
|
-
[ 0x13F, 0xA5 ],
|
|
719
|
-
|
|
720
|
-
[ 0x120, 0x08 ],
|
|
721
|
-
[ 0x13F, 0xA5 ]
|
|
774
|
+
[0x120, 0x02],
|
|
775
|
+
[0x13F, 0xA5]
|
|
722
776
|
]
|
|
723
|
-
|
|
777
|
+
return commands
|
|
778
|
+
def lk_dmg_mmsa_map_full(self):
|
|
779
|
+
commands = [
|
|
780
|
+
[0x120, 0x04],
|
|
781
|
+
[0x13F, 0xA5]
|
|
782
|
+
]
|
|
783
|
+
return commands
|
|
784
|
+
def lk_dmg_mmsa_map_menu(self):
|
|
785
|
+
commands = [
|
|
786
|
+
[0x120, 0x05],
|
|
787
|
+
[0x13F, 0xA5]
|
|
788
|
+
]
|
|
789
|
+
return commands
|
|
790
|
+
|
|
791
|
+
def EnableMapper(self):
|
|
792
|
+
dprint(self.GetName())
|
|
793
|
+
self.CartWrite(self.lk_dmg_mmsa_access_mapper())
|
|
794
|
+
self.CartWrite(self.lk_dmg_mmsa_access_mbc(enable=True))
|
|
795
|
+
self.CartWrite(self.lk_dmg_mmsa_map_full())
|
|
796
|
+
self.CartWrite(self.lk_dmg_mmsa_flash_command(0x0, 0xF0))
|
|
797
|
+
self.CartWrite(self.lk_dmg_mmsa_access_rom())
|
|
724
798
|
return True
|
|
725
799
|
|
|
726
800
|
def SelectBankROM(self, index):
|
|
727
801
|
dprint(self.GetName(), "|", index)
|
|
728
802
|
commands = [
|
|
729
|
-
[
|
|
803
|
+
[ 0x2000, index & 0xFF ],
|
|
730
804
|
]
|
|
731
805
|
|
|
732
806
|
start_address = 0 if index == 0 else 0x4000
|
|
@@ -738,63 +812,30 @@ class DMG_GMMC1(DMG_MBC5):
|
|
|
738
812
|
return True
|
|
739
813
|
|
|
740
814
|
def ReadHiddenSector(self):
|
|
741
|
-
|
|
742
|
-
|
|
743
|
-
|
|
744
|
-
|
|
745
|
-
|
|
746
|
-
|
|
747
|
-
[
|
|
748
|
-
|
|
749
|
-
|
|
750
|
-
|
|
751
|
-
|
|
752
|
-
|
|
753
|
-
|
|
754
|
-
[
|
|
755
|
-
|
|
756
|
-
|
|
757
|
-
|
|
758
|
-
|
|
759
|
-
|
|
760
|
-
|
|
761
|
-
|
|
762
|
-
|
|
763
|
-
|
|
764
|
-
|
|
765
|
-
|
|
766
|
-
[ 0x120, 0x0F ],
|
|
767
|
-
[ 0x125, 0x2A ],
|
|
768
|
-
[ 0x126, 0xAA ],
|
|
769
|
-
[ 0x127, 0x55 ],
|
|
770
|
-
[ 0x13F, 0xA5 ],
|
|
771
|
-
|
|
772
|
-
[ 0x120, 0x0F ],
|
|
773
|
-
[ 0x125, 0x55 ],
|
|
774
|
-
[ 0x126, 0x55 ],
|
|
775
|
-
[ 0x127, 0x77 ],
|
|
776
|
-
[ 0x13F, 0xA5 ],
|
|
777
|
-
|
|
778
|
-
[ 0x120, 0x0F ],
|
|
779
|
-
[ 0x125, 0x55 ],
|
|
780
|
-
[ 0x126, 0x55 ],
|
|
781
|
-
[ 0x127, 0xAA ],
|
|
782
|
-
[ 0x13F, 0xA5 ],
|
|
783
|
-
|
|
784
|
-
[ 0x120, 0x0F ],
|
|
785
|
-
[ 0x125, 0x2A ],
|
|
786
|
-
[ 0x126, 0xAA ],
|
|
787
|
-
[ 0x127, 0x55 ],
|
|
788
|
-
[ 0x13F, 0xA5 ],
|
|
789
|
-
|
|
790
|
-
[ 0x120, 0x0F ],
|
|
791
|
-
[ 0x125, 0x55 ],
|
|
792
|
-
[ 0x126, 0x55 ],
|
|
793
|
-
[ 0x127, 0x77 ],
|
|
794
|
-
[ 0x13F, 0xA5 ]
|
|
795
|
-
]
|
|
796
|
-
self.CartWrite(commands)
|
|
797
|
-
return self.CartRead(0, 128)
|
|
815
|
+
hp = 5
|
|
816
|
+
while hp > 0:
|
|
817
|
+
self.EnableMapper()
|
|
818
|
+
rom = self.CartRead(0, 128)
|
|
819
|
+
self.CartWrite(self.lk_dmg_mmsa_access_mapper())
|
|
820
|
+
self.CartWrite(self.lk_dmg_mmsa_access_mbc(enable=True))
|
|
821
|
+
self.CartWrite([[0x2100, 0x1]])
|
|
822
|
+
self.CartWrite(self.lk_dmg_mmsa_flash_command(0x5555, 0xAA))
|
|
823
|
+
self.CartWrite(self.lk_dmg_mmsa_flash_command(0x2AAA, 0x55))
|
|
824
|
+
self.CartWrite(self.lk_dmg_mmsa_flash_command(0x5555, 0x77))
|
|
825
|
+
self.CartWrite(self.lk_dmg_mmsa_flash_command(0x5555, 0xAA))
|
|
826
|
+
self.CartWrite(self.lk_dmg_mmsa_flash_command(0x2AAA, 0x55))
|
|
827
|
+
self.CartWrite(self.lk_dmg_mmsa_flash_command(0x5555, 0x77))
|
|
828
|
+
self.CartWrite([[0x2100, 0x0]])
|
|
829
|
+
hs = self.CartRead(0, 128)
|
|
830
|
+
self.CartWrite(self.lk_dmg_mmsa_access_rom())
|
|
831
|
+
if hs != rom: break
|
|
832
|
+
hp -= 1
|
|
833
|
+
dprint("HP:", hp, hs)
|
|
834
|
+
|
|
835
|
+
if hp > 0:
|
|
836
|
+
return hs
|
|
837
|
+
else:
|
|
838
|
+
return False
|
|
798
839
|
|
|
799
840
|
def CalcChecksum(self, buffer):
|
|
800
841
|
header = RomFileDMG(buffer[:0x180]).GetHeader()
|
|
@@ -927,52 +968,20 @@ class DMG_HuC3(DMG_MBC):
|
|
|
927
968
|
ts = int(time.time())
|
|
928
969
|
buffer.extend(struct.pack("<Q", ts))
|
|
929
970
|
|
|
930
|
-
|
|
931
|
-
|
|
971
|
+
dstr = ' '.join(format(x, '02X') for x in buffer)
|
|
972
|
+
dprint("RTC: [{:02X}] {:s}".format(int(len(dstr)/3) + 1, dstr))
|
|
932
973
|
|
|
933
974
|
self.RTC_BUFFER = buffer
|
|
934
975
|
return buffer
|
|
935
976
|
|
|
936
|
-
def
|
|
937
|
-
|
|
938
|
-
|
|
939
|
-
|
|
940
|
-
|
|
941
|
-
|
|
942
|
-
|
|
943
|
-
|
|
944
|
-
days = 0
|
|
945
|
-
else:
|
|
946
|
-
data = struct.unpack("<I", buffer[0:4])[0]
|
|
947
|
-
hours = math.floor((data & 0xFFF) / 60)
|
|
948
|
-
minutes = (data & 0xFFF) % 60
|
|
949
|
-
days = (data >> 12) & 0xFFF
|
|
950
|
-
|
|
951
|
-
timestamp_then = struct.unpack("<Q", buffer[-8:])[0]
|
|
952
|
-
timestamp_now = int(time.time())
|
|
953
|
-
dprint(hours, minutes, days)
|
|
954
|
-
if timestamp_then < timestamp_now:
|
|
955
|
-
dt_then = datetime.datetime.fromtimestamp(timestamp_then)
|
|
956
|
-
dt_buffer1 = datetime.datetime.strptime("{:04d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}".format(1, 1, 1, 0, 0, 0), "%Y-%m-%d %H:%M:%S")
|
|
957
|
-
dt_buffer2 = datetime.datetime.strptime("{:04d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}".format(1, 1, 1, hours, minutes, 0), "%Y-%m-%d %H:%M:%S")
|
|
958
|
-
dt_buffer2 += datetime.timedelta(days=days)
|
|
959
|
-
rd = relativedelta(dt_now, dt_then)
|
|
960
|
-
dt_new = dt_buffer2 + rd
|
|
961
|
-
dprint(dt_then, dt_now, dt_buffer1, dt_buffer2, dt_new, sep="\n")
|
|
962
|
-
minutes = dt_new.minute
|
|
963
|
-
hours = dt_new.hour
|
|
964
|
-
#temp = dt_new - dt_buffer1
|
|
965
|
-
#days = temp.days
|
|
966
|
-
temp = datetime.date.fromtimestamp(timestamp_now) - datetime.date.fromtimestamp(timestamp_then)
|
|
967
|
-
days = temp.days + days
|
|
968
|
-
dprint(minutes, hours, days)
|
|
969
|
-
|
|
970
|
-
total_minutes = 60 * hours + minutes
|
|
971
|
-
data = (total_minutes & 0xFFF) | ((days & 0xFFF) << 12)
|
|
972
|
-
buffer[0:4] = struct.pack("<I", data)
|
|
973
|
-
|
|
974
|
-
except Exception as e:
|
|
975
|
-
print("Couldn’t update the RTC register values\n", e)
|
|
977
|
+
def WriteRTCDict(self, rtc_dict):
|
|
978
|
+
dprint("Writing RTC:", rtc_dict)
|
|
979
|
+
self.EnableRAM(enable=True)
|
|
980
|
+
|
|
981
|
+
total_minutes = 60 * rtc_dict["rtc_h"] + rtc_dict["rtc_m"]
|
|
982
|
+
data = (total_minutes & 0xFFF) | ((rtc_dict["rtc_d"] & 0xFFF) << 12)
|
|
983
|
+
buffer = bytearray(4)
|
|
984
|
+
buffer[0:4] = struct.pack("<I", data)
|
|
976
985
|
|
|
977
986
|
commands = [
|
|
978
987
|
[ 0x0000, 0x0B ],
|
|
@@ -1026,18 +1035,79 @@ class DMG_HuC3(DMG_MBC):
|
|
|
1026
1035
|
self.CartWrite(commands, delay=0.03)
|
|
1027
1036
|
dstr = ' '.join(format(x, '02X') for x in buffer)
|
|
1028
1037
|
dprint("[{:02X}] {:s}".format(int(len(dstr)/3) + 1, dstr))
|
|
1038
|
+
return True
|
|
1039
|
+
|
|
1040
|
+
def WriteRTC(self, buffer, advance=False):
|
|
1041
|
+
if advance:
|
|
1042
|
+
try:
|
|
1043
|
+
dt_now = datetime.datetime.fromtimestamp(time.time())
|
|
1044
|
+
dprint(buffer)
|
|
1045
|
+
if buffer == bytearray([0x00] * len(buffer)): # Reset
|
|
1046
|
+
hours = 0
|
|
1047
|
+
minutes = 0
|
|
1048
|
+
days = 0
|
|
1049
|
+
else:
|
|
1050
|
+
data = struct.unpack("<I", buffer[0:4])[0]
|
|
1051
|
+
hours = math.floor((data & 0xFFF) / 60)
|
|
1052
|
+
minutes = (data & 0xFFF) % 60
|
|
1053
|
+
days = (data >> 12) & 0xFFF
|
|
1054
|
+
|
|
1055
|
+
timestamp_then = struct.unpack("<Q", buffer[-8:])[0]
|
|
1056
|
+
timestamp_now = int(time.time())
|
|
1057
|
+
dprint(hours, minutes, days)
|
|
1058
|
+
if timestamp_then < timestamp_now:
|
|
1059
|
+
dt_then = datetime.datetime.fromtimestamp(timestamp_then)
|
|
1060
|
+
dt_buffer1 = datetime.datetime.strptime("{:04d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}".format(1, 1, 1, 0, 0, 0), "%Y-%m-%d %H:%M:%S")
|
|
1061
|
+
dt_buffer2 = datetime.datetime.strptime("{:04d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}".format(1, 1, 1, hours, minutes, 0), "%Y-%m-%d %H:%M:%S")
|
|
1062
|
+
dt_buffer2 += datetime.timedelta(days=days)
|
|
1063
|
+
rd = relativedelta(dt_now, dt_then)
|
|
1064
|
+
dt_new = dt_buffer2 + rd
|
|
1065
|
+
dprint(dt_then, dt_now, dt_buffer1, dt_buffer2, dt_new, sep="\n")
|
|
1066
|
+
minutes = dt_new.minute
|
|
1067
|
+
hours = dt_new.hour
|
|
1068
|
+
#temp = dt_new - dt_buffer1
|
|
1069
|
+
#days = temp.days
|
|
1070
|
+
temp = datetime.date.fromtimestamp(timestamp_now) - datetime.date.fromtimestamp(timestamp_then)
|
|
1071
|
+
days = temp.days + days
|
|
1072
|
+
dprint(minutes, hours, days)
|
|
1073
|
+
|
|
1074
|
+
#total_minutes = 60 * hours + minutes
|
|
1075
|
+
#data = (total_minutes & 0xFFF) | ((days & 0xFFF) << 12)
|
|
1076
|
+
#buffer[0:4] = struct.pack("<I", data)
|
|
1077
|
+
d = {
|
|
1078
|
+
"rtc_h":hours,
|
|
1079
|
+
"rtc_m":minutes,
|
|
1080
|
+
"rtc_d":days
|
|
1081
|
+
}
|
|
1082
|
+
self.WriteRTCDict(d)
|
|
1083
|
+
|
|
1084
|
+
except Exception as e:
|
|
1085
|
+
print("Couldn’t update the RTC register values\n", e)
|
|
1029
1086
|
|
|
1030
|
-
def
|
|
1087
|
+
def GetRTCDict(self):
|
|
1031
1088
|
if self.RTC_BUFFER is None:
|
|
1032
1089
|
self.ReadRTC()
|
|
1033
1090
|
rtc_buffer = struct.unpack("<I", self.RTC_BUFFER[0:4])[0]
|
|
1034
1091
|
rtc_h = math.floor((rtc_buffer & 0xFFF) / 60)
|
|
1035
1092
|
rtc_m = (rtc_buffer & 0xFFF) % 60
|
|
1036
1093
|
rtc_d = (rtc_buffer >> 12) & 0xFFF
|
|
1094
|
+
|
|
1095
|
+
d = {
|
|
1096
|
+
"rtc_h":rtc_h,
|
|
1097
|
+
"rtc_m":rtc_m,
|
|
1098
|
+
"rtc_d":rtc_d,
|
|
1099
|
+
"rtc_valid":True
|
|
1100
|
+
}
|
|
1101
|
+
|
|
1037
1102
|
if rtc_d == 1:
|
|
1038
|
-
|
|
1103
|
+
d["string"] = "{:d} day, {:02d}:{:02d}".format(rtc_d, rtc_h, rtc_m)
|
|
1039
1104
|
else:
|
|
1040
|
-
|
|
1105
|
+
d["string"] = "{:d} days, {:02d}:{:02d}".format(rtc_d, rtc_h, rtc_m)
|
|
1106
|
+
|
|
1107
|
+
return d
|
|
1108
|
+
|
|
1109
|
+
def GetRTCString(self):
|
|
1110
|
+
return self.GetRTCDict()["string"]
|
|
1041
1111
|
|
|
1042
1112
|
def GetMaxROMSize(self):
|
|
1043
1113
|
return 2*1024*1024
|
|
@@ -1127,6 +1197,73 @@ class DMG_TAMA5(DMG_MBC):
|
|
|
1127
1197
|
self.RTC_BUFFER = buffer
|
|
1128
1198
|
return buffer
|
|
1129
1199
|
|
|
1200
|
+
def WriteRTCDict(self, rtc_dict):
|
|
1201
|
+
buffer = rtc_dict["rtc_buffer"]
|
|
1202
|
+
buffer[0x00] = Util.EncodeBCD(rtc_dict["rtc_s"])
|
|
1203
|
+
buffer[0x01] = Util.EncodeBCD(rtc_dict["rtc_i"])
|
|
1204
|
+
buffer[0x02] = Util.EncodeBCD(rtc_dict["rtc_h"])
|
|
1205
|
+
buffer[0x03] = ((Util.EncodeBCD(rtc_dict["rtc_d"]) & 0xF) << 4) | 6 #weekday?
|
|
1206
|
+
buffer[0x04] = (Util.EncodeBCD(rtc_dict["rtc_d"]) >> 4) | ((Util.EncodeBCD(rtc_dict["rtc_m"]) & 0xF) << 4)
|
|
1207
|
+
buffer[0x05] = (Util.EncodeBCD(rtc_dict["rtc_m"]) >> 4) | ((Util.EncodeBCD(rtc_dict["rtc_y"]) & 0xF) << 4)
|
|
1208
|
+
buffer[0x06] = (Util.EncodeBCD(rtc_dict["rtc_y"]) >> 4)
|
|
1209
|
+
buffer[0x0D] = rtc_dict["rtc_leap_year_state"] << 4 | 1 #24h flag
|
|
1210
|
+
|
|
1211
|
+
for page in range(0, 5):
|
|
1212
|
+
if page == 0:
|
|
1213
|
+
commands = [
|
|
1214
|
+
# Select TAMA6
|
|
1215
|
+
[ 0xA001, 0x06 ],
|
|
1216
|
+
[ 0xA000, 0x04 ],
|
|
1217
|
+
# Stop timer
|
|
1218
|
+
[ 0xA001, 0x06 ],
|
|
1219
|
+
[ 0xA000, 0x04 ],
|
|
1220
|
+
[ 0xA001, 0x07 ],
|
|
1221
|
+
[ 0xA000, 0x00 ],
|
|
1222
|
+
]
|
|
1223
|
+
commands = [
|
|
1224
|
+
# Select TAMA6
|
|
1225
|
+
[ 0xA001, 0x06 ],
|
|
1226
|
+
[ 0xA000, 0x04 ],
|
|
1227
|
+
# Reset timer
|
|
1228
|
+
[ 0xA001, 0x06 ],
|
|
1229
|
+
[ 0xA000, 0x04 ],
|
|
1230
|
+
[ 0xA001, 0x07 ],
|
|
1231
|
+
[ 0xA000, 0x01 ],
|
|
1232
|
+
]
|
|
1233
|
+
self.CartWrite(commands, sram=True)
|
|
1234
|
+
|
|
1235
|
+
page_buffer = buffer[page*8:page*8+8]
|
|
1236
|
+
for reg in range(0, 0x0D):
|
|
1237
|
+
commands = [
|
|
1238
|
+
# Select RTC
|
|
1239
|
+
[ 0xA001, 0x06 ],
|
|
1240
|
+
[ 0xA000, 0x08 ],
|
|
1241
|
+
# Select RTC register
|
|
1242
|
+
[ 0xA001, 0x04 ],
|
|
1243
|
+
[ 0xA000, reg ],
|
|
1244
|
+
# Set data
|
|
1245
|
+
[ 0xA001, 0x05 ]
|
|
1246
|
+
]
|
|
1247
|
+
self.CartWrite(commands, sram=True)
|
|
1248
|
+
if reg % 2 == 0:
|
|
1249
|
+
self.CartWrite([[ 0xA000, page_buffer[reg>>1] & 0xF ]], sram=True)
|
|
1250
|
+
else:
|
|
1251
|
+
self.CartWrite([[ 0xA000, page_buffer[reg>>1] >> 4 ]], sram=True)
|
|
1252
|
+
commands = [
|
|
1253
|
+
# Select RTC operation
|
|
1254
|
+
[ 0xA001, 0x07 ],
|
|
1255
|
+
[ 0xA000, (page << 1) ],
|
|
1256
|
+
# Read data
|
|
1257
|
+
[ 0xA001, 0x0C ]
|
|
1258
|
+
]
|
|
1259
|
+
self.CartWrite(commands, sram=True)
|
|
1260
|
+
value1, value2 = None, None
|
|
1261
|
+
while value1 is None or value1 != value2:
|
|
1262
|
+
value2 = value1
|
|
1263
|
+
value1 = self.CartRead(0xA000)
|
|
1264
|
+
|
|
1265
|
+
return True
|
|
1266
|
+
|
|
1130
1267
|
def WriteRTC(self, buffer, advance=False):
|
|
1131
1268
|
if advance:
|
|
1132
1269
|
try:
|
|
@@ -1140,7 +1277,7 @@ class DMG_TAMA5(DMG_MBC):
|
|
|
1140
1277
|
months = 1
|
|
1141
1278
|
years = 0
|
|
1142
1279
|
leap_year_state = 0
|
|
1143
|
-
z24h_flag = 1
|
|
1280
|
+
#z24h_flag = 1
|
|
1144
1281
|
else:
|
|
1145
1282
|
#dstr = ' '.join(format(x, '02X') for x in buffer)
|
|
1146
1283
|
#print("[{:02X}] {:s}".format(int(len(dstr)/3) + 1, dstr))
|
|
@@ -1153,7 +1290,7 @@ class DMG_TAMA5(DMG_MBC):
|
|
|
1153
1290
|
months = Util.DecodeBCD(buffer[0x04] >> 4 | (buffer[0x05] & 0xF) << 4)
|
|
1154
1291
|
years = Util.DecodeBCD(buffer[0x05] >> 4 | (buffer[0x06] & 0xF) << 4)
|
|
1155
1292
|
leap_year_state = Util.DecodeBCD(buffer[0x0D] >> 4)
|
|
1156
|
-
z24h_flag = Util.DecodeBCD(buffer[0x0D] & 0xF)
|
|
1293
|
+
#z24h_flag = Util.DecodeBCD(buffer[0x0D] & 0xF)
|
|
1157
1294
|
#print("Old:", seconds, minutes, hours, day_of_week, days, months, years, leap_year_state, z24h_flag)
|
|
1158
1295
|
|
|
1159
1296
|
timestamp_then = struct.unpack("<Q", buffer[-8:])[0]
|
|
@@ -1190,14 +1327,14 @@ class DMG_TAMA5(DMG_MBC):
|
|
|
1190
1327
|
#print("leap_year_state#2", leap_year_state)
|
|
1191
1328
|
#print("New:", seconds, minutes, hours, day_of_week, days, months, years, leap_year_state, z24h_flag)
|
|
1192
1329
|
|
|
1193
|
-
buffer[0x00] = Util.EncodeBCD(seconds)
|
|
1194
|
-
buffer[0x01] = Util.EncodeBCD(minutes)
|
|
1195
|
-
buffer[0x02] = Util.EncodeBCD(hours)
|
|
1196
|
-
buffer[0x03] = (weekday & 0xF) | ((Util.EncodeBCD(days) & 0xF) << 4)
|
|
1197
|
-
buffer[0x04] = (Util.EncodeBCD(days) >> 4) | ((Util.EncodeBCD(months) & 0xF) << 4)
|
|
1198
|
-
buffer[0x05] = (Util.EncodeBCD(months) >> 4) | ((Util.EncodeBCD(years) & 0xF) << 4)
|
|
1199
|
-
buffer[0x06] = (Util.EncodeBCD(years) >> 4)
|
|
1200
|
-
buffer[0x0D] = leap_year_state << 4 | z24h_flag
|
|
1330
|
+
# buffer[0x00] = Util.EncodeBCD(seconds)
|
|
1331
|
+
# buffer[0x01] = Util.EncodeBCD(minutes)
|
|
1332
|
+
# buffer[0x02] = Util.EncodeBCD(hours)
|
|
1333
|
+
# buffer[0x03] = (weekday & 0xF) | ((Util.EncodeBCD(days) & 0xF) << 4)
|
|
1334
|
+
# buffer[0x04] = (Util.EncodeBCD(days) >> 4) | ((Util.EncodeBCD(months) & 0xF) << 4)
|
|
1335
|
+
# buffer[0x05] = (Util.EncodeBCD(months) >> 4) | ((Util.EncodeBCD(years) & 0xF) << 4)
|
|
1336
|
+
# buffer[0x06] = (Util.EncodeBCD(years) >> 4)
|
|
1337
|
+
# buffer[0x0D] = leap_year_state << 4 | z24h_flag
|
|
1201
1338
|
|
|
1202
1339
|
#dstr = ' '.join(format(x, '02X') for x in buffer)
|
|
1203
1340
|
#print("[{:02X}] {:s}".format(int(len(dstr)/3) + 1, dstr))
|
|
@@ -1205,61 +1342,20 @@ class DMG_TAMA5(DMG_MBC):
|
|
|
1205
1342
|
except Exception as e:
|
|
1206
1343
|
print("Couldn’t update the RTC register values\n", e)
|
|
1207
1344
|
|
|
1208
|
-
|
|
1209
|
-
|
|
1210
|
-
|
|
1211
|
-
|
|
1212
|
-
|
|
1213
|
-
|
|
1214
|
-
|
|
1215
|
-
|
|
1216
|
-
|
|
1217
|
-
|
|
1218
|
-
|
|
1219
|
-
|
|
1220
|
-
|
|
1221
|
-
|
|
1222
|
-
[ 0xA001, 0x06 ],
|
|
1223
|
-
[ 0xA000, 0x04 ],
|
|
1224
|
-
# Reset timer
|
|
1225
|
-
[ 0xA001, 0x06 ],
|
|
1226
|
-
[ 0xA000, 0x04 ],
|
|
1227
|
-
[ 0xA001, 0x07 ],
|
|
1228
|
-
[ 0xA000, 0x01 ],
|
|
1229
|
-
]
|
|
1230
|
-
self.CartWrite(commands, sram=True)
|
|
1231
|
-
|
|
1232
|
-
page_buffer = buffer[page*8:page*8+8]
|
|
1233
|
-
for reg in range(0, 0x0D):
|
|
1234
|
-
commands = [
|
|
1235
|
-
# Select RTC
|
|
1236
|
-
[ 0xA001, 0x06 ],
|
|
1237
|
-
[ 0xA000, 0x08 ],
|
|
1238
|
-
# Select RTC register
|
|
1239
|
-
[ 0xA001, 0x04 ],
|
|
1240
|
-
[ 0xA000, reg ],
|
|
1241
|
-
# Set data
|
|
1242
|
-
[ 0xA001, 0x05 ]
|
|
1243
|
-
]
|
|
1244
|
-
self.CartWrite(commands, sram=True)
|
|
1245
|
-
if reg % 2 == 0:
|
|
1246
|
-
self.CartWrite([[ 0xA000, page_buffer[reg>>1] & 0xF ]], sram=True)
|
|
1247
|
-
else:
|
|
1248
|
-
self.CartWrite([[ 0xA000, page_buffer[reg>>1] >> 4 ]], sram=True)
|
|
1249
|
-
commands = [
|
|
1250
|
-
# Select RTC operation
|
|
1251
|
-
[ 0xA001, 0x07 ],
|
|
1252
|
-
[ 0xA000, (page << 1) ],
|
|
1253
|
-
# Read data
|
|
1254
|
-
[ 0xA001, 0x0C ]
|
|
1255
|
-
]
|
|
1256
|
-
self.CartWrite(commands, sram=True)
|
|
1257
|
-
value1, value2 = None, None
|
|
1258
|
-
while value1 is None or value1 != value2:
|
|
1259
|
-
value2 = value1
|
|
1260
|
-
value1 = self.CartRead(0xA000)
|
|
1261
|
-
|
|
1262
|
-
def GetRTCString(self):
|
|
1345
|
+
d = {
|
|
1346
|
+
"rtc_y":years,
|
|
1347
|
+
"rtc_m":months,
|
|
1348
|
+
"rtc_d":days,
|
|
1349
|
+
"rtc_h":hours,
|
|
1350
|
+
"rtc_i":minutes,
|
|
1351
|
+
"rtc_s":seconds,
|
|
1352
|
+
"rtc_leap_year_state":leap_year_state,
|
|
1353
|
+
"rtc_buffer":buffer,
|
|
1354
|
+
"rtc_valid":True
|
|
1355
|
+
}
|
|
1356
|
+
self.WriteRTCDict(d)
|
|
1357
|
+
|
|
1358
|
+
def GetRTCDict(self):
|
|
1263
1359
|
if self.RTC_BUFFER is None:
|
|
1264
1360
|
self.ReadRTC()
|
|
1265
1361
|
rtc_buffer = self.RTC_BUFFER
|
|
@@ -1271,11 +1367,28 @@ class DMG_TAMA5(DMG_MBC):
|
|
|
1271
1367
|
months = Util.DecodeBCD(rtc_buffer[0x04] >> 4 | (rtc_buffer[0x05] & 0xF) << 4)
|
|
1272
1368
|
years = Util.DecodeBCD(rtc_buffer[0x05] >> 4 | (rtc_buffer[0x06] & 0xF) << 4)
|
|
1273
1369
|
leap_year_state = Util.DecodeBCD(rtc_buffer[0x0D] >> 4)
|
|
1370
|
+
|
|
1371
|
+
d = {
|
|
1372
|
+
"rtc_y":years,
|
|
1373
|
+
"rtc_m":months,
|
|
1374
|
+
"rtc_d":days,
|
|
1375
|
+
#"rtc_w":weekday,
|
|
1376
|
+
"rtc_h":hours,
|
|
1377
|
+
"rtc_i":minutes,
|
|
1378
|
+
"rtc_s":seconds,
|
|
1379
|
+
"rtc_leap_year_state":leap_year_state,
|
|
1380
|
+
"rtc_buffer":rtc_buffer,
|
|
1381
|
+
"rtc_valid":True
|
|
1382
|
+
}
|
|
1383
|
+
|
|
1274
1384
|
if leap_year_state == 0:
|
|
1275
|
-
|
|
1385
|
+
d["string"] = "{:d} year(s)ᴸ, {:d}-{:d}, {:02d}:{:02d}:{:02d}".format(years - 19, months, days, hours, minutes, seconds)
|
|
1276
1386
|
else:
|
|
1277
|
-
|
|
1278
|
-
|
|
1387
|
+
d["string"] = "{:d} year(s), {:d}-{:d}, {:02d}:{:02d}:{:02d}".format(years - 19, months, days, hours, minutes, seconds)
|
|
1388
|
+
return d
|
|
1389
|
+
|
|
1390
|
+
def GetRTCString(self):
|
|
1391
|
+
return self.GetRTCDict()["string"]
|
|
1279
1392
|
|
|
1280
1393
|
def ReadWithCSPulse(self):
|
|
1281
1394
|
return False
|
|
@@ -1297,7 +1410,10 @@ class DMG_Unlicensed_256M(DMG_MBC5):
|
|
|
1297
1410
|
flash_bank = math.floor(index / 512)
|
|
1298
1411
|
dprint(self.GetName(), "|SelectBankFlash()|", index, "->", flash_bank)
|
|
1299
1412
|
|
|
1300
|
-
self.
|
|
1413
|
+
if self.CURRENT_FLASH_BANK != flash_bank:
|
|
1414
|
+
dprint("Power cycling now")
|
|
1415
|
+
self.CART_POWERCYCLE_FNCPTR()
|
|
1416
|
+
self.CURRENT_FLASH_BANK = flash_bank
|
|
1301
1417
|
|
|
1302
1418
|
commands = [
|
|
1303
1419
|
[ 0x7000, 0x00 ],
|
|
@@ -1308,7 +1424,7 @@ class DMG_Unlicensed_256M(DMG_MBC5):
|
|
|
1308
1424
|
self.CartWrite(commands, delay=0.1)
|
|
1309
1425
|
|
|
1310
1426
|
def SelectBankROM(self, index):
|
|
1311
|
-
dprint(self.GetName(),
|
|
1427
|
+
dprint(self.GetName(), index)
|
|
1312
1428
|
|
|
1313
1429
|
if (index % 512 == 0) or (self.CURRENT_FLASH_BANK != math.floor(index / 512)):
|
|
1314
1430
|
self.SelectBankFlash(index)
|
|
@@ -1333,6 +1449,8 @@ class DMG_Unlicensed_256M(DMG_MBC5):
|
|
|
1333
1449
|
if index % 4 == 0:
|
|
1334
1450
|
self.EnableRAM(enable=False)
|
|
1335
1451
|
self.CART_POWERCYCLE_FNCPTR()
|
|
1452
|
+
self.CURRENT_FLASH_BANK = flash_bank
|
|
1453
|
+
|
|
1336
1454
|
commands = [
|
|
1337
1455
|
[ 0x7000, (0x40 * math.floor(index / 4)) & 0xFF ],
|
|
1338
1456
|
[ 0x7001, 0xC0 ],
|
|
@@ -1385,15 +1503,18 @@ class DMG_Unlicensed_XploderGB(DMG_MBC):
|
|
|
1385
1503
|
def SelectBankROM(self, index):
|
|
1386
1504
|
dprint(self.GetName(), "|", index)
|
|
1387
1505
|
if index == 0:
|
|
1506
|
+
self.CartRead(0x0102, 1)
|
|
1388
1507
|
self.CART_POWERCYCLE_FNCPTR()
|
|
1389
1508
|
self.CartRead(0x0102, 1)
|
|
1390
1509
|
self.CartWrite([[ 0x0006, index & 0xFF ]])
|
|
1510
|
+
self.CURRENT_ROM_BANK = index
|
|
1391
1511
|
start_address = 0x4000
|
|
1392
1512
|
return (start_address, self.ROM_BANK_SIZE)
|
|
1393
1513
|
|
|
1394
1514
|
def SelectBankRAM(self, index):
|
|
1395
1515
|
dprint(self.GetName(), "|", index)
|
|
1396
1516
|
if index == 0:
|
|
1517
|
+
self.CartRead(0x0102, 1)
|
|
1397
1518
|
self.CART_POWERCYCLE_FNCPTR()
|
|
1398
1519
|
self.CartRead(0x0102, 1)
|
|
1399
1520
|
return self.SelectBankROM(index + 8)
|
|
@@ -1479,8 +1600,8 @@ class AGB_GPIO:
|
|
|
1479
1600
|
|
|
1480
1601
|
# Commands
|
|
1481
1602
|
RTC_RESET = 0x60
|
|
1482
|
-
|
|
1483
|
-
|
|
1603
|
+
RTC_WRITE_STATUS = 0x62
|
|
1604
|
+
RTC_READ_STATUS = 0x63
|
|
1484
1605
|
RTC_WRITE_DATE = 0x64
|
|
1485
1606
|
RTC_READ_DATE = 0x65
|
|
1486
1607
|
RTC_WRITE_TIME = 0x66
|
|
@@ -1502,10 +1623,10 @@ class AGB_GPIO:
|
|
|
1502
1623
|
data = self.CART_READ_FNCPTR(address)
|
|
1503
1624
|
data = struct.pack(">H", data)
|
|
1504
1625
|
data = struct.unpack("<H", data)[0]
|
|
1505
|
-
dprint("0x{:X} is 0x{:X}".format(address, data))
|
|
1626
|
+
#dprint("0x{:X} is 0x{:X}".format(address, data))
|
|
1506
1627
|
else:
|
|
1507
1628
|
data = self.CART_READ_FNCPTR(address, length)
|
|
1508
|
-
dprint("0x{:X} is".format(address), data)
|
|
1629
|
+
#dprint("0x{:X} is".format(address), data)
|
|
1509
1630
|
|
|
1510
1631
|
return data
|
|
1511
1632
|
|
|
@@ -1513,7 +1634,7 @@ class AGB_GPIO:
|
|
|
1513
1634
|
for command in commands:
|
|
1514
1635
|
address = command[0]
|
|
1515
1636
|
value = command[1]
|
|
1516
|
-
dprint("0x{:X} = 0x{:X}".format(address, value))
|
|
1637
|
+
# dprint("0x{:X} = 0x{:X}".format(address, value))
|
|
1517
1638
|
self.CART_WRITE_FNCPTR(address, value)
|
|
1518
1639
|
if delay is not False: time.sleep(delay)
|
|
1519
1640
|
|
|
@@ -1538,9 +1659,10 @@ class AGB_GPIO:
|
|
|
1538
1659
|
[ self.GPIO_REG_DAT, 4 ],
|
|
1539
1660
|
[ self.GPIO_REG_DAT, 5 ]
|
|
1540
1661
|
])
|
|
1541
|
-
|
|
1662
|
+
temp = self.CartRead(self.GPIO_REG_DAT) & 0xFF
|
|
1663
|
+
bit = (temp & 2) >> 1
|
|
1542
1664
|
data = (data >> 1) | (bit << 7)
|
|
1543
|
-
|
|
1665
|
+
# print("RTCReadData(): i={:d}/temp={:X}/bit={:x}/data={:x}".format(i, temp, bit, data))
|
|
1544
1666
|
return data
|
|
1545
1667
|
|
|
1546
1668
|
def RTCWriteData(self, data):
|
|
@@ -1560,7 +1682,7 @@ class AGB_GPIO:
|
|
|
1560
1682
|
[ self.GPIO_REG_DAT, 5 ],
|
|
1561
1683
|
[ self.GPIO_REG_CNT, 7 ], # Write Enable
|
|
1562
1684
|
])
|
|
1563
|
-
self.RTCCommand(self.
|
|
1685
|
+
self.RTCCommand(self.RTC_READ_STATUS)
|
|
1564
1686
|
self.CartWrite([
|
|
1565
1687
|
[ self.GPIO_REG_CNT, 5 ], # Read Enable
|
|
1566
1688
|
])
|
|
@@ -1579,7 +1701,7 @@ class AGB_GPIO:
|
|
|
1579
1701
|
[ self.GPIO_REG_DAT, 5 ],
|
|
1580
1702
|
[ self.GPIO_REG_CNT, 7 ], # Write Enable
|
|
1581
1703
|
])
|
|
1582
|
-
self.RTCCommand(self.
|
|
1704
|
+
self.RTCCommand(self.RTC_WRITE_STATUS)
|
|
1583
1705
|
self.RTCWriteData(value)
|
|
1584
1706
|
|
|
1585
1707
|
self.CartWrite([
|
|
@@ -1588,11 +1710,15 @@ class AGB_GPIO:
|
|
|
1588
1710
|
[ self.GPIO_REG_RE, 0 ], # Disable RTC Mapping
|
|
1589
1711
|
])
|
|
1590
1712
|
|
|
1591
|
-
def HasRTC(self):
|
|
1713
|
+
def HasRTC(self, buffer=None):
|
|
1592
1714
|
if not self.RTC: return False
|
|
1715
|
+
if buffer is not None: self.RTC_BUFFER = buffer[1:]
|
|
1593
1716
|
|
|
1594
|
-
|
|
1595
|
-
|
|
1717
|
+
if buffer is None:
|
|
1718
|
+
status = self.RTCReadStatus()
|
|
1719
|
+
else:
|
|
1720
|
+
status = buffer[0]
|
|
1721
|
+
|
|
1596
1722
|
if (status >> 7) == 1:
|
|
1597
1723
|
dprint("No RTC because of set RTC Status Register Power Flag:", status >> 7 & 1)
|
|
1598
1724
|
return 1
|
|
@@ -1601,41 +1727,46 @@ class AGB_GPIO:
|
|
|
1601
1727
|
#return 2
|
|
1602
1728
|
|
|
1603
1729
|
rom1 = self.CartRead(self.GPIO_REG_DAT, 6)
|
|
1604
|
-
|
|
1605
|
-
|
|
1606
|
-
|
|
1607
|
-
|
|
1608
|
-
|
|
1609
|
-
|
|
1610
|
-
|
|
1611
|
-
|
|
1730
|
+
if buffer is None:
|
|
1731
|
+
self.CartWrite([
|
|
1732
|
+
[ self.GPIO_REG_RE, 1 ], # Enable RTC Mapping
|
|
1733
|
+
])
|
|
1734
|
+
rom2 = self.CartRead(self.GPIO_REG_DAT, 6)
|
|
1735
|
+
self.CartWrite([
|
|
1736
|
+
[ self.GPIO_REG_RE, 0 ], # Disable RTC Mapping
|
|
1737
|
+
])
|
|
1738
|
+
else:
|
|
1739
|
+
rom2 = buffer[1:7]
|
|
1740
|
+
|
|
1741
|
+
dprint(' '.join(format(x, '02X') for x in rom1), "/", ' '.join(format(x, '02X') for x in rom2))
|
|
1612
1742
|
if (rom1 == rom2):
|
|
1613
1743
|
dprint("No RTC because ROM data didn’t change:", rom1, rom2)
|
|
1614
1744
|
return 3
|
|
1615
|
-
|
|
1745
|
+
|
|
1616
1746
|
return True
|
|
1617
1747
|
|
|
1618
|
-
def ReadRTC(self):
|
|
1748
|
+
def ReadRTC(self, buffer=None):
|
|
1619
1749
|
if not self.RTC: return False
|
|
1620
|
-
|
|
1621
|
-
|
|
1622
|
-
|
|
1623
|
-
|
|
1624
|
-
|
|
1625
|
-
|
|
1626
|
-
|
|
1627
|
-
|
|
1628
|
-
|
|
1629
|
-
|
|
1630
|
-
|
|
1631
|
-
|
|
1632
|
-
|
|
1633
|
-
|
|
1634
|
-
|
|
1635
|
-
|
|
1636
|
-
|
|
1637
|
-
|
|
1638
|
-
|
|
1750
|
+
if buffer is None:
|
|
1751
|
+
self.CartWrite([
|
|
1752
|
+
[ self.GPIO_REG_RE, 1 ], # Enable RTC Mapping
|
|
1753
|
+
[ self.GPIO_REG_DAT, 1 ],
|
|
1754
|
+
[ self.GPIO_REG_DAT, 5 ],
|
|
1755
|
+
[ self.GPIO_REG_CNT, 7 ], # Write Enable
|
|
1756
|
+
])
|
|
1757
|
+
self.RTCCommand(self.RTC_READ_DATE)
|
|
1758
|
+
self.CartWrite([
|
|
1759
|
+
[ self.GPIO_REG_CNT, 5 ], # Read Enable
|
|
1760
|
+
])
|
|
1761
|
+
buffer = bytearray()
|
|
1762
|
+
for _ in range(0, 7):
|
|
1763
|
+
buffer.append(self.RTCReadData())
|
|
1764
|
+
|
|
1765
|
+
self.CartWrite([
|
|
1766
|
+
[ self.GPIO_REG_DAT, 1 ],
|
|
1767
|
+
[ self.GPIO_REG_DAT, 1 ],
|
|
1768
|
+
[ self.GPIO_REG_RE, 0 ], # Disable RTC Mapping
|
|
1769
|
+
])
|
|
1639
1770
|
|
|
1640
1771
|
# Add timestamp of backup time
|
|
1641
1772
|
ts = int(time.time())
|
|
@@ -1653,48 +1784,80 @@ class AGB_GPIO:
|
|
|
1653
1784
|
self.RTC_BUFFER = buffer
|
|
1654
1785
|
return buffer
|
|
1655
1786
|
|
|
1787
|
+
def WriteRTCDict(self, rtc_dict):
|
|
1788
|
+
buffer = bytearray(7)
|
|
1789
|
+
try:
|
|
1790
|
+
buffer[0] = Util.EncodeBCD(rtc_dict["rtc_y"])
|
|
1791
|
+
buffer[1] = Util.EncodeBCD(rtc_dict["rtc_m"])
|
|
1792
|
+
buffer[2] = Util.EncodeBCD(rtc_dict["rtc_d"])
|
|
1793
|
+
buffer[3] = Util.EncodeBCD(rtc_dict["rtc_w"])
|
|
1794
|
+
buffer[4] = Util.EncodeBCD(rtc_dict["rtc_h"])
|
|
1795
|
+
if buffer[4] >= 12: buffer[4] |= 0x80
|
|
1796
|
+
buffer[5] = Util.EncodeBCD(rtc_dict["rtc_i"])
|
|
1797
|
+
buffer[6] = Util.EncodeBCD(rtc_dict["rtc_s"])
|
|
1798
|
+
dprint("New values: RTC_Y=0x{:02X}, RTC_M=0x{:02X}, RTC_D=0x{:02X}, RTC_W=0x{:02X}, RTC_H=0x{:02X}, RTC_I=0x{:02X}, RTC_S=0x{:02X}".format(buffer[0], buffer[1], buffer[2], buffer[3], buffer[4], buffer[5], buffer[6]))
|
|
1799
|
+
except ValueError as e:
|
|
1800
|
+
print("Couldn’t update the RTC register values\n", e)
|
|
1801
|
+
|
|
1802
|
+
self.CartWrite([
|
|
1803
|
+
[ self.GPIO_REG_RE, 1 ], # Enable RTC Mapping
|
|
1804
|
+
[ self.GPIO_REG_DAT, 1 ],
|
|
1805
|
+
[ self.GPIO_REG_DAT, 5 ],
|
|
1806
|
+
[ self.GPIO_REG_CNT, 7 ], # Write Enable
|
|
1807
|
+
])
|
|
1808
|
+
self.RTCCommand(self.RTC_WRITE_DATE)
|
|
1809
|
+
for i in range(0, 7):
|
|
1810
|
+
self.RTCWriteData(buffer[i])
|
|
1811
|
+
|
|
1812
|
+
self.CartWrite([
|
|
1813
|
+
[ self.GPIO_REG_DAT, 1 ],
|
|
1814
|
+
[ self.GPIO_REG_DAT, 1 ],
|
|
1815
|
+
[ self.GPIO_REG_RE, 0 ], # Disable RTC Mapping
|
|
1816
|
+
])
|
|
1817
|
+
return True
|
|
1818
|
+
|
|
1656
1819
|
def WriteRTC(self, buffer, advance=False):
|
|
1657
1820
|
rtc_status = None
|
|
1821
|
+
if buffer == bytearray([0xFF] * len(buffer)): # Reset
|
|
1822
|
+
years = 0
|
|
1823
|
+
months = 1
|
|
1824
|
+
days = 1
|
|
1825
|
+
weekday = 0
|
|
1826
|
+
hours = 0
|
|
1827
|
+
minutes = 0
|
|
1828
|
+
seconds = 0
|
|
1829
|
+
rtc_status = 0x40 | 0x80
|
|
1830
|
+
else:
|
|
1831
|
+
years = Util.DecodeBCD(buffer[0x00])
|
|
1832
|
+
months = Util.DecodeBCD(buffer[0x01])
|
|
1833
|
+
days = Util.DecodeBCD(buffer[0x02])
|
|
1834
|
+
weekday = Util.DecodeBCD(buffer[0x03])
|
|
1835
|
+
hours = Util.DecodeBCD(buffer[0x04] & 0x7F)
|
|
1836
|
+
minutes = Util.DecodeBCD(buffer[0x05])
|
|
1837
|
+
seconds = Util.DecodeBCD(buffer[0x06])
|
|
1838
|
+
rtc_status = buffer[0x07]
|
|
1839
|
+
if rtc_status == 0x01: rtc_status = 0x40 # old dumps had this value
|
|
1840
|
+
|
|
1658
1841
|
if advance:
|
|
1659
1842
|
try:
|
|
1660
1843
|
dt_now = datetime.datetime.fromtimestamp(time.time())
|
|
1661
|
-
|
|
1662
|
-
|
|
1663
|
-
|
|
1664
|
-
|
|
1665
|
-
|
|
1666
|
-
|
|
1667
|
-
|
|
1668
|
-
|
|
1669
|
-
|
|
1670
|
-
|
|
1671
|
-
|
|
1672
|
-
|
|
1673
|
-
|
|
1674
|
-
weekday
|
|
1675
|
-
hours =
|
|
1676
|
-
minutes =
|
|
1677
|
-
seconds =
|
|
1678
|
-
rtc_status = buffer[0x07]
|
|
1679
|
-
if rtc_status == 0x01: rtc_status = 0x40 # old dumps had this value
|
|
1680
|
-
|
|
1681
|
-
timestamp_then = struct.unpack("<Q", buffer[-8:])[0]
|
|
1682
|
-
timestamp_now = int(time.time())
|
|
1683
|
-
if timestamp_then < timestamp_now:
|
|
1684
|
-
dt_then = datetime.datetime.fromtimestamp(timestamp_then)
|
|
1685
|
-
dt_buffer = datetime.datetime.strptime("{:04d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}".format(years + 2000, months % 13, days % 32, hours % 60, minutes % 60, seconds % 60), "%Y-%m-%d %H:%M:%S")
|
|
1686
|
-
rd = relativedelta(dt_now, dt_then)
|
|
1687
|
-
dt_new = dt_buffer + rd
|
|
1688
|
-
years = dt_new.year - 2000
|
|
1689
|
-
months = dt_new.month
|
|
1690
|
-
days = dt_new.day
|
|
1691
|
-
dt_buffer_notime = dt_buffer.replace(hour=0, minute=0, second=0)
|
|
1692
|
-
dt_new_notime = dt_new.replace(hour=0, minute=0, second=0)
|
|
1693
|
-
days_passed = int((dt_new_notime.timestamp() - dt_buffer_notime.timestamp()) / 60 / 60 / 24)
|
|
1694
|
-
weekday += days_passed % 7
|
|
1695
|
-
hours = dt_new.hour
|
|
1696
|
-
minutes = dt_new.minute
|
|
1697
|
-
seconds = dt_new.second
|
|
1844
|
+
timestamp_then = struct.unpack("<Q", buffer[-8:])[0]
|
|
1845
|
+
timestamp_now = int(time.time())
|
|
1846
|
+
if timestamp_then < timestamp_now:
|
|
1847
|
+
dt_then = datetime.datetime.fromtimestamp(timestamp_then)
|
|
1848
|
+
dt_buffer = datetime.datetime.strptime("{:04d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}".format(years + 2000, months % 13, days % 32, hours % 60, minutes % 60, seconds % 60), "%Y-%m-%d %H:%M:%S")
|
|
1849
|
+
rd = relativedelta(dt_now, dt_then)
|
|
1850
|
+
dt_new = dt_buffer + rd
|
|
1851
|
+
years = dt_new.year - 2000
|
|
1852
|
+
months = dt_new.month
|
|
1853
|
+
days = dt_new.day
|
|
1854
|
+
dt_buffer_notime = dt_buffer.replace(hour=0, minute=0, second=0)
|
|
1855
|
+
dt_new_notime = dt_new.replace(hour=0, minute=0, second=0)
|
|
1856
|
+
days_passed = int((dt_new_notime.timestamp() - dt_buffer_notime.timestamp()) / 60 / 60 / 24)
|
|
1857
|
+
weekday += days_passed % 7
|
|
1858
|
+
hours = dt_new.hour
|
|
1859
|
+
minutes = dt_new.minute
|
|
1860
|
+
seconds = dt_new.second
|
|
1698
1861
|
|
|
1699
1862
|
#dprint(years, months, days, weekday, hours, minutes, seconds)
|
|
1700
1863
|
buffer[0x00] = Util.EncodeBCD(years)
|
|
@@ -1712,48 +1875,63 @@ class AGB_GPIO:
|
|
|
1712
1875
|
except Exception as e:
|
|
1713
1876
|
print("Couldn’t update the RTC register values\n", e)
|
|
1714
1877
|
|
|
1715
|
-
|
|
1716
|
-
|
|
1717
|
-
|
|
1718
|
-
|
|
1719
|
-
|
|
1720
|
-
|
|
1721
|
-
|
|
1722
|
-
|
|
1723
|
-
|
|
1724
|
-
|
|
1725
|
-
self.
|
|
1726
|
-
[ self.GPIO_REG_DAT, 1 ],
|
|
1727
|
-
[ self.GPIO_REG_DAT, 1 ],
|
|
1728
|
-
[ self.GPIO_REG_RE, 0 ], # Disable RTC Mapping
|
|
1729
|
-
])
|
|
1878
|
+
d = {
|
|
1879
|
+
"rtc_y":years,
|
|
1880
|
+
"rtc_m":months,
|
|
1881
|
+
"rtc_d":days,
|
|
1882
|
+
"rtc_w":weekday,
|
|
1883
|
+
"rtc_h":hours,
|
|
1884
|
+
"rtc_i":minutes,
|
|
1885
|
+
"rtc_s":seconds,
|
|
1886
|
+
}
|
|
1887
|
+
dprint(d)
|
|
1888
|
+
self.WriteRTCDict(d)
|
|
1730
1889
|
|
|
1731
1890
|
if rtc_status is not None:
|
|
1732
1891
|
self.RTCWriteStatus(rtc_status)
|
|
1733
1892
|
|
|
1734
|
-
def
|
|
1735
|
-
has_rtc
|
|
1893
|
+
def GetRTCDict(self, has_rtc=None):
|
|
1894
|
+
if has_rtc is None:
|
|
1895
|
+
has_rtc = self.HasRTC()
|
|
1736
1896
|
if has_rtc is not True:
|
|
1737
|
-
if has_rtc is False:
|
|
1738
|
-
return "Not available"
|
|
1897
|
+
if has_rtc is False or has_rtc in (2, 3):
|
|
1898
|
+
return {"string":"Not available"}
|
|
1739
1899
|
elif has_rtc == 1:
|
|
1740
|
-
return "Not available / Battery dry"
|
|
1741
|
-
|
|
1742
|
-
return "Not available"
|
|
1743
|
-
|
|
1900
|
+
return {"string":"Not available / Battery dry"}
|
|
1901
|
+
|
|
1744
1902
|
if self.RTC_BUFFER is None:
|
|
1745
1903
|
self.ReadRTC()
|
|
1746
1904
|
rtc_buffer = self.RTC_BUFFER
|
|
1905
|
+
|
|
1747
1906
|
#weekdays = ['Sun', 'Mon', 'Tue', 'Wed', 'Thu', 'Fri', 'Sat']
|
|
1748
1907
|
rtc_y = (rtc_buffer[0] & 0x0F) + ((rtc_buffer[0] >> 4) * 10)
|
|
1749
1908
|
rtc_m = (rtc_buffer[1] & 0x0F) + ((rtc_buffer[1] >> 4) * 10)
|
|
1750
1909
|
rtc_d = (rtc_buffer[2] & 0x0F) + ((rtc_buffer[2] >> 4) * 10)
|
|
1751
|
-
|
|
1910
|
+
rtc_w = (rtc_buffer[3] & 0x0F) + ((rtc_buffer[3] >> 4) * 10)
|
|
1752
1911
|
rtc_h = ((rtc_buffer[4] & 0x0F) + (((rtc_buffer[4] >> 4) & 0x7) * 10))
|
|
1753
1912
|
rtc_i = (rtc_buffer[5] & 0x0F) + ((rtc_buffer[5] >> 4) * 10)
|
|
1754
1913
|
rtc_s = (rtc_buffer[6] & 0x0F) + ((rtc_buffer[6] >> 4) * 10)
|
|
1755
1914
|
|
|
1915
|
+
d = {
|
|
1916
|
+
"rtc_y":rtc_y,
|
|
1917
|
+
"rtc_m":rtc_m,
|
|
1918
|
+
"rtc_d":rtc_d,
|
|
1919
|
+
"rtc_w":rtc_w,
|
|
1920
|
+
"rtc_h":rtc_h,
|
|
1921
|
+
"rtc_i":rtc_i,
|
|
1922
|
+
"rtc_s":rtc_s,
|
|
1923
|
+
"rtc_24h":rtc_buffer[0] >> 6 & 1
|
|
1924
|
+
}
|
|
1925
|
+
|
|
1756
1926
|
if rtc_y == 0 and rtc_m == 0 and rtc_d == 0 and rtc_h == 0 and rtc_i == 0 and rtc_s == 0:
|
|
1757
|
-
raise
|
|
1927
|
+
#raise ValueError("Invalid RTC data")
|
|
1928
|
+
d["string"] = "Invalid RTC data"
|
|
1929
|
+
d["rtc_valid"] = False
|
|
1758
1930
|
else:
|
|
1759
|
-
|
|
1931
|
+
d["string"] = "20{:02d}-{:02d}-{:02d} {:02d}:{:02d}:{:02d}".format(rtc_y, rtc_m, rtc_d, rtc_h, rtc_i, rtc_s)
|
|
1932
|
+
d["rtc_valid"] = True
|
|
1933
|
+
|
|
1934
|
+
return d
|
|
1935
|
+
|
|
1936
|
+
def GetRTCString(self, has_rtc=None):
|
|
1937
|
+
return self.GetRTCDict(has_rtc=has_rtc)["string"]
|