better handling of mid-track transition to built-in RWTS

This commit is contained in:
4am 2019-02-02 11:50:34 -05:00
parent dd8761c7c5
commit 5b411eb582
2 changed files with 205 additions and 113 deletions

View File

@ -162,6 +162,7 @@ class BasePassportProcessor: # base class
self.g.logger.PrintByID("sync")
return True
# TODO IsUnformatted nibble test and other tests
# (still need these for disks like Crime Wave and Thunder Bombs)
return False
def IDDiversi(self, t00s00):
@ -179,103 +180,32 @@ class BasePassportProcessor: # base class
def IDDavidDOS(self, t00s00):
"""returns True if T00S00 is David-DOS II bootloader, or False otherwise"""
if not find.at(0x01, t00s00,
b'\xA5\x27'
b'\xC9\x09'
b'\xD0\x17'):
return False
return find.wild_at(0x4A, t00s00,
b'\xA2' + find.WILDCARD + \
b'\xBD' + find.WILDCARD + b'\x08' + \
b'\x9D' + find.WILDCARD + b'\x04' + \
b'\xCA'
b'\x10\xF7')
return find.at(0x01, t00s00, kIDDavidDOS1) and \
find.wild_at(0x4A, t00s00, kIDDavidDOS2)
def IDDatasoft(self, t00s00):
"""returns True if T00S00 is encrypted Datasoft bootloader, or False otherwise"""
return find.at(0x00, t00s00,
b'\x01\x4C\x7E\x08\x04\x8A\x0C\xB8'
b'\x00\x56\x10\x7A\x00\x00\x1A\x16'
b'\x12\x0E\x0A\x06\x53\x18\x9A\x02'
b'\x10\x1B\x02\x10\x4D\x56\x15\x0B'
b'\xBF\x14\x14\x54\x54\x54\x92\x81'
b'\x1B\x10\x10\x41\x06\x73\x0A\x10'
b'\x33\x4E\x00\x73\x12\x10\x33\x7C'
b'\x00\x11\x20\xE3\x49\x50\x73\x1A'
b'\x10\x41\x00\x23\x80\x5B\x0A\x10'
b'\x0B\x4E\x9D\x0A\x10\x9D\x0C\x10'
b'\x60\x1E\x53\x10\x90\x53\xBC\x90'
b'\x53\x00\x90\xD8\x52\x00\xD8\x7C'
b'\x00\x53\x80\x0B\x06\x41\x00\x09'
b'\x04\x45\x0C\x63\x04\x90\x94\xD0'
b'\xD4\x23\x04\x91\xA1\xEB\xCD\x06'
b'\x95\xA1\xE1\x98\x97\x86')
return find.at(0x00, t00s00, kIDDatasoft)
def IDMicrograms(self, t00s00):
"""returns True if T00S00 is Micrograms bootloader, or False otherwise"""
if not find.at(0x01, t00s00,
b'\xA5\x27'
b'\xC9\x09'
b'\xD0\x12'
b'\xA9\xC6'
b'\x85\x3F'):
return False
return find.at(0x42, t00s00, b'\x4C\x00')
return find.at(0x01, t00s00, kIDMicrograms1) and \
find.at(0x42, t00s00, kIDMicrograms2)
def IDQuickDOS(self, t00s00):
"""returns True if T00S00 is Quick-DOS bootloader, or False otherwise"""
return find.at(0x01, t00s00,
b'\xA5\x27'
b'\xC9\x09'
b'\xD0\x27'
b'\x78'
b'\xAD\x83\xC0')
return find.at(0x01, t00s00, kIDQuickDOS)
def IDRDOS(self, t00s00):
"""returns True if T00S00 is Quick-DOS bootloader, or False otherwise"""
return find.at(0x00, t00s00,
b'\x01'
b'\xA9\x60'
b'\x8D\x01\x08'
b'\xA2\x00'
b'\xA0\x1F'
b'\xB9\x00\x08'
b'\x49')
return find.at(0x00, t00s00, kIDRDOS)
def IDDOS33(self, t00s00):
"""returns True if T00S00 is DOS bootloader or some variation
that can be safely boot traced, or False otherwise"""
# Code at $0801 must be standard (with one exception)
if not find.wild_at(0x00, t00s00,
b'\x01'
b'\xA5\x27'
b'\xC9\x09'
b'\xD0\x18'
b'\xA5\x2B'
b'\x4A'
b'\x4A'
b'\x4A'
b'\x4A'
b'\x09\xC0'
b'\x85\x3F'
b'\xA9\x5C'
b'\x85\x3E'
b'\x18'
b'\xAD\xFE\x08'
b'\x6D\xFF\x08' + \
find.WILDCARD + find.WILDCARD + find.WILDCARD + \
b'\xAE\xFF\x08'
b'\x30\x15'
b'\xBD\x4D\x08'
b'\x85\x3D'
b'\xCE\xFF\x08'
b'\xAD\xFE\x08'
b'\x85\x27'
b'\xCE\xFE\x08'
b'\xA6\x2B'
b'\x6C\x3E\x00'
b'\xEE\xFE\x08'
b'\xEE\xFE\x08'): return False
if not find.wild_at(0x00, t00s00, kIDDOS33a):
return False
# DOS 3.3 has JSR $FE89 / JSR $FE93 / JSR $FB2F
# some Sierra have STA $C050 / STA $C057 / STA $C055 instead
# with the unpleasant side-effect of showing text-mode garbage
@ -661,43 +591,53 @@ class BasePassportProcessor: # base class
# main loop - loop through disk from track $22 down to track $00
for logical_track_num in range(0x22, -1, -1):
self.g.track = logical_track_num # for display purposes only
self.g.logger.debug("Seeking to track %s" % hex(self.g.track))
# distinguish between logical and physical track numbers to deal with
# disks like Sunburst that store logical track 0x11+ on physical track 0x11.5+
physical_track_num = self.rwts.seek(logical_track_num)
# self.tracks must be indexed by physical track number so we can write out
# .woz files correctly
self.tracks[physical_track_num] = self.g.disk_image.seek(physical_track_num)
self.g.logger.debug("Seeking to track %s" % hex(self.g.track))
tried_reseek = False
physical_sectors = OrderedDict()
while True:
physical_sectors = self.rwts.decode_track(self.tracks[physical_track_num], logical_track_num, self.burn)
physical_sectors.update(self.rwts.decode_track(self.tracks[physical_track_num], logical_track_num, self.burn))
if self.rwts.enough(logical_track_num, physical_sectors):
break
if supports_reseek and not tried_reseek:
self.tracks[physical_track_num] = self.g.disk_image.reseek(physical_track_num)
self.g.logger.debug("Reseeking to track %s" % hex(self.g.track))
tried_reseek = True
continue
self.g.logger.debug("found %d sectors" % len(physical_sectors))
if (0x0F not in physical_sectors) and self.SkipTrack(logical_track_num, self.tracks[physical_track_num]):
physical_sectors = None
break
if self.g.tried_univ:
if logical_track_num == 0x22 and (0x0F not in physical_sectors):
self.g.logger.PrintByID("fail")
self.g.logger.PrintByID("fatal220f")
return False
else:
# TODO wrong in case where we switch mid-track.
# Need to save the sectors that worked with the original RWTS
# then append the ones that worked with the universal RWTS
self.g.logger.PrintByID("switch", {"sector":0x0F}) # TODO find exact sector
transition_sector = 0x0F
if physical_sectors:
temp_logical_sectors = self.rwts.reorder_to_logical_sectors(physical_sectors)
transition_sector = min(temp_logical_sectors.keys())
self.g.logger.PrintByID("switch", {"sector":transition_sector})
self.rwts = UniversalRWTS(self.g)
self.g.tried_univ = True
continue
if logical_track_num == 0 and type(self.rwts) != UniversalRWTSIgnoreEpilogues:
self.rwts = UniversalRWTSIgnoreEpilogues(self.g)
continue
self.g.logger.PrintByID("fail")
return False
self.save_track(physical_track_num, logical_track_num, physical_sectors)
@ -711,37 +651,14 @@ class BasePassportProcessor: # base class
class Verify(BasePassportProcessor):
def AnalyzeT00(self, logical_sectors):
self.g.is_boot1 = find.at(0x00, logical_sectors[1],
b'\x8E\xE9\xB7\x8E\xF7\xB7\xA9\x01'
b'\x8D\xF8\xB7\x8D\xEA\xB7\xAD\xE0'
b'\xB7\x8D\xE1\xB7\xA9\x02\x8D\xEC'
b'\xB7\xA9\x04\x8D\xED\xB7\xAC\xE7'
b'\xB7\x88\x8C\xF1\xB7\xA9\x01\x8D'
b'\xF4\xB7\x8A\x4A\x4A\x4A\x4A\xAA'
b'\xA9\x00\x9D\xF8\x04\x9D\x78\x04')
self.g.is_master = find.at(0x00, logical_sectors[1],
b'\x8E\xE9\x37\x8E\xF7\x37\xA9\x01'
b'\x8D\xF8\x37\x8D\xEA\x37\xAD\xE0'
b'\x37\x8D\xE1\x37\xA9\x02\x8D\xEC'
b'\x37\xA9\x04\x8D\xED\x37\xAC\xE7'
b'\x37\x88\x8C\xF1\x37\xA9\x01\x8D'
b'\xF4\x37\x8A\x4A\x4A\x4A\x4A\xAA'
b'\xA9\x00\x9D\xF8\x04\x9D\x78\x04')
self.g.is_rwts = find.wild_at(0x00, logical_sectors[7],
b'\x84\x48\x85\x49\xA0\x02\x8C' + find.WILDCARD + \
find.WILDCARD + b'\xA0\x04\x8C' + find.WILDCARD + find.WILDCARD + b'\xA0\x01' + \
b'\xB1\x48\xAA\xA0\x0F\xD1\x48\xF0'
b'\x1B\x8A\x48\xB1\x48\xAA\x68\x48'
b'\x91\x48\xBD\x8E\xC0\xA0\x08\xBD'
b'\x8C\xC0\xDD\x8C\xC0\xD0\xF6\x88'
b'\xD0\xF8\x68\xAA\xBD\x8E\xC0\xBD'
b'\x8C\xC0\xA0\x08\xBD\x8C\xC0\x48')
self.g.is_boot1 = find.at(0x00, logical_sectors[1], kIDBoot1)
self.g.is_master = find.at(0x00, logical_sectors[1], kIDMaster)
self.g.is_rwts = find.wild_at(0x00, logical_sectors[7], kIDRWTS)
def save_track(self, physical_track_num, logical_track_num, physical_sectors):
if not physical_sectors: return {}
logical_sectors = self.rwts.reorder_to_logical_sectors(physical_sectors)
should_run_patchers = (len(physical_sectors) == 16) # TODO
if should_run_patchers:
if self.rwts.enough(logical_track_num, physical_sectors):
# patchers operate on logical tracks
if logical_track_num == 0:
# set additional globals for patchers to use

View File

@ -1,5 +1,94 @@
from passport.util import *
kIDBoot1 = bytes.fromhex(
"8E E9 B7"
"8E F7 B7"
"A9 01"
"8D F8 B7"
"8D EA B7"
"AD E0 B7"
"8D E1 B7"
"A9 02"
"8D EC B7"
"A9 04"
"8D ED B7"
"AC E7 B7"
"88"
"8C F1 B7"
"A9 01"
"8D F4 B7"
"8A"
"4A"
"4A"
"4A"
"4A"
"AA"
"A9 00"
"9D F8 04"
"9D 78 04")
kIDMaster = bytes.fromhex(
"8E E9 37"
"8E F7 37"
"A9 01"
"8D F8 37"
"8D EA 37"
"AD E0 37"
"8D E1 37"
"A9 02"
"8D EC 37"
"A9 04"
"8D ED 37"
"AC E7 37"
"88"
"8C F1 37"
"A9 01"
"8D F4 37"
"8A"
"4A"
"4A"
"4A"
"4A"
"AA"
"A9 00"
"9D F8 04"
"9D 78 04")
kIDRWTS = bytes.fromhex(
"84 48"
"85 49"
"A0 02"
"8C" + find.WILDSTR + find.WILDSTR + \
"A0 04"
"8C" + find.WILDSTR + find.WILDSTR + \
"A0 01"
"B1 48"
"AA"
"A0 0F"
"D1 48"
"F0 1B"
"8A"
"48"
"B1 48"
"AA"
"68"
"48"
"91 48"
"BD 8E C0"
"A0 08"
"BD 8C C0"
"DD 8C C0"
"D0 F6"
"88"
"D0 F8"
"68"
"AA"
"BD 8E C0"
"BD 8C C0"
"A0 08"
"BD 8C C0"
"48")
kIDDiversiDOSBootloader = bytes.fromhex("B3 A3 A0 D2 CF D2 D2 C5 8D 87 8D")
kIDProDOSBootloader = bytes.fromhex(
@ -20,3 +109,89 @@ kIDPascalBootloader2 = bytes.fromhex(
"B0 04" # BCS +4
"E0 40" # CPX #$40
"B0") # BCS
kIDDavidDOS1 = bytes.fromhex(
"A5 27"
"C9 09"
"D0 17")
kIDDavidDOS2 = bytes.fromhex(
"A2" + find.WILDSTR + \
"BD" + find.WILDSTR + " 08" + \
"9D" + find.WILDSTR + " 04" + \
"CA"
"10 F7")
kIDDatasoft = bytes.fromhex(
"01 4C 7E 08 04 8A 0C B8"
"00 56 10 7A 00 00 1A 16"
"12 0E 0A 06 53 18 9A 02"
"10 1B 02 10 4D 56 15 0B"
"BF 14 14 54 54 54 92 81"
"1B 10 10 41 06 73 0A 10"
"33 4E 00 73 12 10 33 7C"
"00 11 20 E3 49 50 73 1A"
"10 41 00 23 80 5B 0A 10"
"0B 4E 9D 0A 10 9D 0C 10"
"60 1E 53 10 90 53 BC 90"
"53 00 90 D8 52 00 D8 7C"
"00 53 80 0B 06 41 00 09"
"04 45 0C 63 04 90 94 D0"
"D4 23 04 91 A1 EB CD 06"
"95 A1 E1 98 97 86")
kIDMicrograms1 = bytes.fromhex(
"A5 27"
"C9 09"
"D0 12"
"A9 C6"
"85 3F")
kIDMicrograms2 = bytes.fromhex("4C 00")
kIDQuickDOS = bytes.fromhex(
"A5 27"
"C9 09"
"D0 27"
"78"
"AD 83 C0")
kIDRDOS = bytes.fromhex(
"01"
"A9 60"
"8D 01 08"
"A2 00"
"A0 1F"
"B9 00 08"
"49")
kIDDOS33a = bytes.fromhex(
"01"
"A5 27"
"C9 09"
"D0 18"
"A5 2B"
"4A"
"4A"
"4A"
"4A"
"09 C0"
"85 3F"
"A9 5C"
"85 3E"
"18"
"AD FE 08"
"6D FF 08" + \
find.WILDSTR + find.WILDSTR + find.WILDSTR + \
"AE FF 08"
"30 15"
"BD 4D 08"
"85 3D"
"CE FF 08"
"AD FE 08"
"85 27"
"CE FE 08"
"A6 2B"
"6C 3E 00"
"EE FE 08"
"EE FE 08")