Initial recognition of 5200 carts by sha1 signature

This commit is contained in:
Rob McMullen 2018-11-08 10:12:53 -08:00
parent 9a638fa951
commit d22f2cdf3f
5 changed files with 238 additions and 28 deletions

View File

@ -20,7 +20,7 @@ from .kboot import KBootImage, add_xexboot_header
from .segments import SegmentData, SegmentSaver, DefaultSegment, EmptySegment, ObjSegment, RawSectorsSegment, SegmentedFileSegment, user_bit_mask, match_bit_mask, comment_bit_mask, data_style, selected_bit_mask, diff_bit_mask, not_user_bit_mask, interleave_segments, SegmentList, get_style_mask, get_style_bits
from .spartados import SpartaDosDiskImage
from .cartridge import A8CartHeader, AtariCartImage, RomImage
from .parsers import SegmentParser, DefaultSegmentParser, guess_parser_for_mime, guess_parser_for_system, guess_container, iter_parsers, iter_known_segment_parsers, mime_parse_order, parsers_for_filename
from .parsers import SegmentParser, DefaultSegmentParser, guess_parser_by_size, guess_parser_for_mime, guess_parser_for_system, guess_container, iter_parsers, iter_known_segment_parsers, mime_parse_order, parsers_for_filename
from .magic import guess_detail_for_mime
from .utils import to_numpy, text_to_int
from .dummy import LocalFilesystem
@ -67,18 +67,20 @@ def find_diskimage(filename, verbose=False):
if container is not None:
data = container.unpacked
rawdata = SegmentData(data)
for mime in mime_parse_order:
if verbose:
print("Trying MIME type %s" % mime)
parser = guess_parser_for_mime(mime, rawdata, verbose)
if parser is None:
continue
if verbose:
print("Found parser %s" % parser.menu_name)
mime2 = guess_detail_for_mime(mime, rawdata, parser)
if mime != mime2 and verbose:
print("Signature match: %s" % mime2)
break
mime, parser = guess_parser_by_size(rawdata)
if parser is None:
for mime in mime_parse_order:
if verbose:
print("Trying MIME type %s" % mime)
parser = guess_parser_for_mime(mime, rawdata, verbose)
if parser is None:
continue
if verbose:
print("Found parser %s" % parser.menu_name)
mime2 = guess_detail_for_mime(mime, rawdata, parser)
if mime != mime2 and verbose:
print("Signature match: %s" % mime2)
break
if parser is None:
raise errors.UnsupportedDiskImage("Unknown disk image type")
else:

View File

@ -223,6 +223,7 @@ class BaseAtariCartImage(DiskImageBase):
# force the header to be the specified cart type
self.header = A8CartHeader()
self.header.set_type(self.cart_type)
self.check_size()
def check_size(self):
if not self.header.valid:
@ -289,14 +290,14 @@ class AtariCartImage(BaseAtariCartImage):
raise errors.InvalidDiskImage("Cart type doesn't match type defined in header")
class Atari8bitCartImage(BaseAtariCartImage):
class Atari8bitCartImage(AtariCartImage):
def strict_check(self):
if "5200" in self.header.cart_name:
raise errors.InvalidDiskImage("5200 Carts don't work in the home computers.")
AtariCartImage.strict_check(self)
class Atari5200CartImage(BaseAtariCartImage):
class Atari5200CartImage(AtariCartImage):
def strict_check(self):
if "5200" not in self.header.cart_name:
raise errors.InvalidDiskImage("Home computer carts don't work in the 5200.")

View File

@ -1,3 +1,5 @@
import hashlib
import numpy as np
from .segments import SegmentData, DefaultSegment
@ -12,6 +14,7 @@ from . import errors
from .magic import guess_detail_for_mime
from . import container
from .dcm import DCMContainer
from .signatures import sha1_signatures
import logging
log = logging.getLogger(__name__)
@ -69,6 +72,7 @@ class SegmentParser:
self.segments.append(self.container_segment(r, 0, name=self.menu_name))
try:
log.debug("Trying %s" % self.image_type)
log.debug(self.image_type.__mro__)
self.image = self.get_image(r)
self.check_image()
self.image.parse_segments()
@ -85,6 +89,7 @@ class SegmentParser:
s.reconstruct_raw(new_rawdata)
def get_image(self, r):
log.info(f"checking image type {self.image_type}")
return self.image_type(r)
def check_image(self):
@ -142,15 +147,16 @@ class AtariCartSegmentParser(SegmentParser):
cart_info = None
def get_image(self, r):
log.info(f"checking cart type {self.cart_type}: {self.image_type}")
return self.image_type(r, self.cart_type)
class Atari8bitCartParser(SegmentParser):
class Atari8bitCartParser(AtariCartSegmentParser):
menu_name = "Atari Home Computer Cartridge"
image_type = Atari8bitCartImage
class Atari5200CartParser(SegmentParser):
class Atari5200CartParser(AtariCartSegmentParser):
menu_name = "Atari 5200 Cartridge"
image_type = Atari5200CartImage
@ -203,6 +209,34 @@ def guess_container(r, verbose=False):
return None
def guess_parser_by_size(r, verbose=False):
found = None
mime = None
size = len(r)
if size in sha1_signatures:
print(r)
sha_hash = hashlib.sha1(r.data).hexdigest()
log.info(f"{size} in signature database, attempting to match {sha_hash}")
try:
match = sha1_signatures[size][sha_hash]
except KeyError:
pass
else:
mime = match[0]
log.info(f"found match: {match}")
parsers = mime_parsers[mime]
for parser in parsers:
try:
found = parser(r, False)
break
except errors.InvalidSegmentParser as e:
if verbose:
log.info("parser isn't %s: %s" % (parser.__name__, str(e)))
pass
if found is None:
log.info(f"no matching signature")
return mime, found
def guess_parser_for_mime(mime, r, verbose=False):
parsers = mime_parsers[mime]
found = None
@ -231,12 +265,15 @@ def iter_parsers(r):
container = guess_container(r.data)
if container is not None:
r = SegmentData(container.unpacked)
for mime in mime_parse_order:
p = guess_parser_for_mime(mime, r)
if p is not None:
mime = guess_detail_for_mime(mime, r, p)
return mime, p
return None, None
mime, parser = guess_parser_by_size(r)
if parser is None:
for mime in mime_parse_order:
p = guess_parser_for_mime(mime, r)
if p is not None:
parser = p
mime = guess_detail_for_mime(mime, r, p)
break
return mime, parser
def parsers_for_filename(name):
@ -274,7 +311,7 @@ mime_parsers = {
"application/vnd.atari8bit.cart": [
Atari8bitCartParser,
],
"application/vnd.atari8bit.5200_cart": [
"application/vnd.atari5200.cart": [
Atari5200CartParser,
],
"application/vnd.mame_rom": [
@ -296,7 +333,7 @@ mime_parse_order = [
"application/vnd.atari8bit.atr",
"application/vnd.atari8bit.xex",
"application/vnd.atari8bit.cart",
"application/vnd.atari8bit.5200_cart",
"application/vnd.atari5200.cart",
"application/vnd.mame_rom",
"application/vnd.apple2.dsk",
"application/vnd.apple2.bin",
@ -307,7 +344,7 @@ pretty_mime = {
"application/vnd.atari8bit.atr": "Atari 8-bit Disk Image",
"application/vnd.atari8bit.xex": "Atari 8-bit Executable",
"application/vnd.atari8bit.cart": "Atari 8-bit Cartridge",
"application/vnd.atari8bit.5200_cart":"Atari 5200 Cartridge",
"application/vnd.atari5200.cart": "Atari 5200 Cartridge",
"application/vnd.mame_rom": "MAME",
"application/vnd.rom": "ROM Image",
"application/vnd.apple2.dsk": "Apple ][ Disk Image",
@ -320,11 +357,12 @@ for k in sizes:
for c in grouped_carts[k]:
t = c[0]
name = c[1]
kclass = type("AtariCartSegmentParser%d" % t, (AtariCartSegmentParser,), {'cart_type': t, 'cart_info': c, 'menu_name': "%s Cartridge" % name})
if "5200" in name:
key = "application/vnd.atari8bit.5200_cart"
key = "application/vnd.atari5200.cart"
kclass = type("Atari5200CartSegmentParser%d" % t, (Atari5200CartParser, AtariCartSegmentParser), {'cart_type': t, 'cart_info': c, 'menu_name': "%s Cartridge" % name})
else:
key = "application/vnd.atari8bit.cart"
kclass = type("Atari8bitCartSegmentParser%d" % t, (Atari8bitCartParser, AtariCartSegmentParser), {'cart_type': t, 'cart_info': c, 'menu_name': "%s Cartridge" % name})
mime_parsers[key].append(kclass)

122
atrcopy/signatures.py Normal file
View File

@ -0,0 +1,122 @@
sha1_signatures = {
2048: {
'6ad7a1e8c9fad486fbec9498cb48bf5bc3adc530': ('application/vnd.atari5200.cart', '[BIOS] Atari 5200 (USA)'),
},
4096: {
'5236bc13e4b06d2e16d70b0a0c98588e1726da0c': ('application/vnd.atari5200.cart', 'Boogie (USA) (Demo)'),
'a80f876a89a8ceacc71da5d9c02b546970b17730': ('application/vnd.atari5200.cart', 'Kaboom! (USA)'),
'f5f9c7f97bf09e5647e808d892b656f3ee1e19e0': ('application/vnd.atari5200.cart', 'Super Breakout (USA)'),
'e58e1f257923694dbeb586c860f385e74e460f90': ('application/vnd.atari5200.cart', 'Yellow Submarine (USA) (Demo)'),
},
8192: {
'e64fb1a353c72b87c5483bb88cb3523ea5d37b59': ('application/vnd.atari5200.cart', '5200 Menu (USA) (Proto)'),
'18697dd8e640fa1578b3b4ae09af484c14fb8410': ('application/vnd.atari5200.cart', 'Asteroids (USA) (Proto)'),
'd3ff99e080985c9c8e25389dfa74835e8c9be508': ('application/vnd.atari5200.cart', "Atari PAM - Pete's Test (USA)"),
'af81c400f1af0ee13a24da5e8b642442a0fc9479': ('application/vnd.atari5200.cart', 'Atari PAM System Test (USA) (v1.02)'),
'ce9bd3b0847c5e187c3e8f667c8f5ea771c49965': ('application/vnd.atari5200.cart', "Carol Shaw's River Raid (USA)"),
'ea7b40ce1106378e1d409cab6634fb2e483ff238': ('application/vnd.atari5200.cart', 'Dreadnaught Factor, The (USA)'),
'd9a695757f0494aee92a50ab8a49558745e0cedf': ('application/vnd.atari5200.cart', 'Frogger (USA)'),
'0df0d7f11d89e2c5b59cc9f98d67d98e203831aa': ('application/vnd.atari5200.cart', 'Galaxian (USA)'),
'80926bb270ea66cb5cacc379de1fc16d8a3d814b': ('application/vnd.atari5200.cart', 'Gorf (USA)'),
'c7eb2b4a46a197adfedf33c2ccc17d8424d681c4': ('application/vnd.atari5200.cart', 'K-Razy Shoot-Out (USA)'),
'9f31c85a13e919135438590601e33bef11a8df8a': ('application/vnd.atari5200.cart', 'Keystone Kapers (USA)'),
'f5512460c6b6d3a1baa0b23adf6a3a37fe308eb3': ('application/vnd.atari5200.cart', 'MegaMania (USA)'),
'5c8ec22e131810ccac08066ca96e9944ccfa4ecb': ('application/vnd.atari5200.cart', 'Missile Command (USA)'),
'2e7ae57260624d1f5710d445a0936f0c280a6655': ('application/vnd.atari5200.cart', 'Mountain King (USA)'),
'002e6f8c7533b03f8041e7f1896589c0ab0e17a6': ('application/vnd.atari5200.cart', "Mr. Do!'s Castle (USA)"),
'd1c7dc3de097a4bfab82235acec69a97e6e05f18': ('application/vnd.atari5200.cart', 'Pitfall! (USA)'),
'e6966bde5cd4167020c9d21bab613af1648b4d75': ('application/vnd.atari5200.cart', 'Q-bert (USA)'),
'cf411db770217b5af5fcfa32725cc587a8b9e710': ('application/vnd.atari5200.cart', 'Space Invaders (USA)'),
'bf77048abc36ba2cba5eeeac812802d6a0eba891': ('application/vnd.atari5200.cart', 'Star Wars - Return of the Jedi - Death Star Battle (USA)'),
'8205093f5fb1fdf0ccb71d667ea0a3849fb0a0f2': ('application/vnd.atari5200.cart', 'Super Cobra (USA)'),
'55da563b4394508c23d866fb1e543262fb45536d': ('application/vnd.atari5200.cart', 'Zenji (USA)'),
},
16384: {
'e18a603b18b85e24f9c938b33b6077a767c1fa9c': ('application/vnd.atari5200.cart', 'A.E. (USA) (Proto)'),
'db203973df13b071da46d52fdb078a76f4db428d': ('application/vnd.atari5200.cart', 'Activision Decathlon, The (USA)'),
'67e405c37e55dec4071018e8166ab4faf9f21df5': ('application/vnd.atari5200.cart', 'Astro Chase (USA)'),
'5cc3b4245faf01c30f77ac20b0b4940f4f8f83d8': ('application/vnd.atari5200.cart', 'Atari PAM Diagnostics (USA) (v2.0)'),
'e086e9868aa913e87f94676fd600f003892e73a1': ('application/vnd.atari5200.cart', 'Atari PAM Diagnostics (USA) (v2.3)'),
'a339cddfc28477c21c58783d2d3b0cf0f4626ddf': ('application/vnd.atari5200.cart', 'Battlezone (USA) (Proto)'),
'b75d555d059ad61992f9f5a234129ecbf9504c35': ('application/vnd.atari5200.cart', 'Beamrider (USA)'),
'e56ccc6bf427a832ce00540b02d065a2688260dc': ('application/vnd.atari5200.cart', 'BerZerk (USA)'),
'ab3130256d16af09cac8b11749dfaff6aaaa3ea3': ('application/vnd.atari5200.cart', 'Blaster (USA) (Proto)'),
'1e1a20c104bf4d55eca0ca1e72dc5dc64fa6b1b5': ('application/vnd.atari5200.cart', 'Blue Print (USA)'),
'bc7c81f758dd3e224e42ac8a16c1a12d69aed722': ('application/vnd.atari5200.cart', 'Buck Rogers - Planet of Zoom (USA)'),
'eb343b90d3de696e69b1f039d4fb2c6afb0d80c0': ('application/vnd.atari5200.cart', 'Centipede (USA)'),
'9f1ee191319ef0261cc7074a81c0e6d6b7464cd2': ('application/vnd.atari5200.cart', 'Choplifter! (USA)'),
'e0203c2124127eba2d679be548fa257ecc5b2607': ('application/vnd.atari5200.cart', 'Congo Bongo (USA)'),
'fa6d77e6e9afd0ea42fc9f9807932bf9e8fb170e': ('application/vnd.atari5200.cart', 'Countermeasure (USA)'),
'b051f0fb2e816787ab6eed0cb008b9f8cc9963dc': ('application/vnd.atari5200.cart', "David Crane's Pitfall II - Lost Caverns (USA)"),
'44f6dbf5013a70e646d5c5232981d517069fc449': ('application/vnd.atari5200.cart', 'Defender (USA)'),
'387a76ba5912251e2285b7722004ad75e9ede523': ('application/vnd.atari5200.cart', 'Dig Dug (USA)'),
'48625af4f3e9fe538dab2a0b463887fc8c6b138d': ('application/vnd.atari5200.cart', 'Final Legacy (USA) (Proto)'),
'69dcc8f59ca449f13dc896b4b29b534762d97064': ('application/vnd.atari5200.cart', 'Frisky Tom (USA) (Proto)'),
'3d815594cf674694b04bb0ff90bf635d7d402fc2': ('application/vnd.atari5200.cart', 'Frogger II - Threeedeep! (USA)'),
'd0d8650eb07d1679004d491360c2c041e37c61cd': ('application/vnd.atari5200.cart', 'Gyruss (USA)'),
'd286ecb6793a0dda9c9c68f6355dbe3ade6922f9': ('application/vnd.atari5200.cart', 'H.E.R.O. (USA)'),
'ae765943ae8d909b6ca6ff1560ba027adeeaa515': ('application/vnd.atari5200.cart', 'James Bond 007 (USA)'),
'0f74125edac90ffd1274a128df2970c239348fb5': ('application/vnd.atari5200.cart', 'Joust (USA)'),
'a3e760d09e4dc6053286967576b5b7d42ee2fd38': ('application/vnd.atari5200.cart', 'Jr. Pac-Man (USA) (Proto)'),
'fa02ee04cfad90c6ccf9d9b984e3b7b3327fec12': ('application/vnd.atari5200.cart', 'Jungle Hunt (USA)'),
'c3dbeed7adc0e282bf76332ab5a3209550e26d02': ('application/vnd.atari5200.cart', 'Kangaroo (USA)'),
'4046f60602254a7d86d2a6efd1a330455eaec119': ('application/vnd.atari5200.cart', 'Last Starfighter, The (USA) (Proto)'),
'bc4a536616ac45689b3ad790f6b1394ebbd8cc7e': ('application/vnd.atari5200.cart', 'Looney Tunes Hotel (USA) (Proto)'),
'32d86a381feff43149b66336dcc4ba2523273228': ('application/vnd.atari5200.cart', 'Meteorites (USA)'),
'2f152a857a8a58d602b3c717612d9744423ee495': ('application/vnd.atari5200.cart', 'Microgammon SB (USA) (Proto)'),
'1243a8ecfc02a74ae4e1f4fcda38502776f45cb0': ('application/vnd.atari5200.cart', 'Millipede (USA) (Proto)'),
'0564b1867a0b570d66dfcbc11adc3e51a2c6f28c': ('application/vnd.atari5200.cart', 'Miner 2049er Starring Bounty Bob (USA)'),
'ef4d3ee7b4da2ef79c6f4d0d1833f10c1eb7725e': ('application/vnd.atari5200.cart', 'Miniature Golf (USA) (Proto)'),
'7e2a05625598c7e6615f969aa695e64315cd9846': ('application/vnd.atari5200.cart', "Montezuma's Revenge featuring Panama Joe (USA)"),
'02dd5b9278c06ae8cbb6dacc094e238fbacf08d2': ('application/vnd.atari5200.cart', 'Moon Patrol (USA)'),
'f93d72444d76075273e508555423936530875148': ('application/vnd.atari5200.cart', 'Ms. Pac-Man (USA)'),
'ee4b3c6f08aa9fdfab532eec98136306b6923f75': ('application/vnd.atari5200.cart', 'Pac-Man (USA)'),
'd504764c5894ee99c0b5e2024cbe833ebba3ab17': ('application/vnd.atari5200.cart', 'Pole Position (USA)'),
'e615aaa0c1d56ac83b91f6087970fa708d6433bf': ('application/vnd.atari5200.cart', 'Popeye (USA)'),
'786cdf54d1625e0d3ea8814506fdeeba5e4ece48': ('application/vnd.atari5200.cart', 'QIX (USA)'),
'17a41c5f9a32f8a71939cfaa0e96807b951aedad': ('application/vnd.atari5200.cart', 'Quest for Quintana Roo (USA)'),
'2b43f74db4833272d2048de8fa32b857af8e090f': ('application/vnd.atari5200.cart', 'RealSports Basketball (USA) (82-11-05) (Proto)'),
'a0dbd654ed3ba2583ca175a1356924d9529884df': ('application/vnd.atari5200.cart', 'RealSports Football (USA)'),
'c911cc914f3923d5aeb1a897e6dc4a551a9a53da': ('application/vnd.atari5200.cart', 'RealSports Soccer (USA)'),
'2e6c7472e37926cdfd3d855a4bd37a18fa83d8cf': ('application/vnd.atari5200.cart', 'RealSports Tennis (USA)'),
'0a7aaef5b0ede927cea13e724906207e1db48068': ('application/vnd.atari5200.cart', 'Road Runner (USA) (Proto)'),
'9175e6daca58102ac8b9729d7b0336cf09977d12': ('application/vnd.atari5200.cart', 'Robotron 2084 (USA)'),
'127ed1c31c3e85d10212eee7b9e6d71aef7dd891': ('application/vnd.atari5200.cart', 'Space Dungeon (USA)'),
'5ae20e767d9819fe601f3b1ea6d4506ae2f2ceef': ('application/vnd.atari5200.cart', 'Space Shuttle - A Journey Into Space (USA)'),
'5f0354d8792d652313e5a0fa5d395e091c801d97': ('application/vnd.atari5200.cart', 'Sport Goofy (USA) (Proto)'),
'57dfc22c9805555f957ed51a2dc7bf35ad00c9d9': ('application/vnd.atari5200.cart', 'Star Raiders (USA)'),
'19801454ab86f2a5cf691fcd577a71ad2b8dc7d5': ('application/vnd.atari5200.cart', 'Star Trek - Strategic Operations Simulator (USA)'),
'ab676ffe054b23bdd43cee2498afefaabbf9355b': ('application/vnd.atari5200.cart', 'Star Wars - The Arcade Game (USA)'),
'09d192a3598cdadfb61eceb430b3d5892e40962f': ('application/vnd.atari5200.cart', 'Stargate (USA) (Proto)'),
'238cb448555d8bb5c96aa0354718411e8777c613': ('application/vnd.atari5200.cart', 'Super Pac-Man (USA) (Proto)'),
'85fcea0a4d4d1f22437801c96229ba96e0f6b711': ('application/vnd.atari5200.cart', 'Tempest (USA) (Proto)'),
'9dfbb5d8b77504c66ce3ac4382daf79820393dd8': ('application/vnd.atari5200.cart', 'Track and Field (USA) (Proto)'),
'49debdf3c133fde9905d6d9137da5d8dff8d6283': ('application/vnd.atari5200.cart', 'Wizard of Wor (USA)'),
'8b5512d3d2a952c99b9377919f0e06481161d81e': ('application/vnd.atari5200.cart', 'Xari Arena (USA) (Proto)'),
'18315bec1e62102290feeb77fb290e1266cf5bfc': ('application/vnd.atari5200.cart', 'Zone Ranger (USA)'),
},
32768: {
'1dfd9cb5eb608590c84e14376291f8c02fb1ab93': ('application/vnd.atari5200.cart', 'Ballblazer (USA)'),
'510ccb20df2ecdbe7f8373de6a9fc11493e8c3f2': ('application/vnd.atari5200.cart', 'Barroom Baseball (USA) (Proto)'),
'9b7ecd444b6239442ef1f54cd8e14c294c064da2': ('application/vnd.atari5200.cart', 'Black Belt (USA) (Proto)'),
'c1a56a1fc51e09b1d8e93af40ddd7596847e6164': ('application/vnd.atari5200.cart', 'Castle Blast (USA) (Unl)'),
'4e022e101d7346a0a8618018372740e7333b4a36': ('application/vnd.atari5200.cart', 'Castle Crisis (USA) (Unl)'),
'f3c32b39580d589799dcead98bb206fbf3df0504': ('application/vnd.atari5200.cart', 'Gremlins (USA)'),
'ca7d5d0871be19ca22d01019fd512b5836e3130a': ('application/vnd.atari5200.cart', 'Joust (USA) 32k'),
'9547c56e2951e1b3a713b0b99d3edb43c9d3cdd8': ('application/vnd.atari5200.cart', 'Koffi - Yellow Kopter (USA) (Unl)'),
'a293b6b06050e11029d97137f2b1b36059567273': ('application/vnd.atari5200.cart', 'Mario Bros. (USA)'),
'ff0f1d9ed0ae45e3c81b252f3d0a335e03b0aa4b': ('application/vnd.atari5200.cart', 'Meebzork (USA) (Proto)'),
'19ff7622dbbc2915e3e98d8d966340e7e893ff34': ('application/vnd.atari5200.cart', 'Pengo (USA)'),
'a94d06739fa19453fa586a836eaacae11fe93989': ('application/vnd.atari5200.cart', 'RealSports Baseball (USA)'),
'9b21ac7fec8d556585c6970231318ef1f501b2b5': ('application/vnd.atari5200.cart', 'RealSports Basketball (USA)'),
'9edb066a37ca7657979952c946ab89be7926f4f8': ('application/vnd.atari5200.cart', 'RealSports Basketball (USA) (83-10-31) (Proto)'),
'9253d7286cf87999474b37df242ba23b4358ef4a': ('application/vnd.atari5200.cart', 'Rescue on Fractalus! (USA)'),
'688133761c462d6865bf673ed298b4d828120940': ('application/vnd.atari5200.cart', 'Spitfire (USA) (Proto)'),
'6c633de50e6cc0c0c40061cd24e6f78f552a438f': ('application/vnd.atari5200.cart', 'Vanguard (USA)'),
'c3cf33216dfa484309b923f21829d040486bc481': ('application/vnd.atari5200.cart', 'Xevious (USA) (Proto)'),
'4a4c4a25c8ed1b0ae79ca22684d7d311a564a7b5': ('application/vnd.atari5200.cart', 'Zaxxon (USA)'),
},
40960: {
'cfdd2f8dabb03d8784f336bb0c804270dc3a8a6c': ('application/vnd.atari5200.cart', 'Bounty Bob Strikes Back! (USA)'),
},
} # end sha1_signatures

47
gen-sha.py Normal file
View File

@ -0,0 +1,47 @@
#!/usr/bin/env python
import os
import sys
import hashlib
from collections import defaultdict
import pprint
def parse(filename, mime):
data = open(filename, 'rb').read()
h = hashlib.sha1(data).hexdigest()
name = os.path.basename(os.path.splitext(filename)[0])
return len(data), h, name
if __name__ == '__main__':
source = "atrcopy/signatures.py"
try:
with open(source, 'r') as fh:
source_text = fh.read()
except OSError:
source_text = "sha1_signatures = {}"
try:
exec(source_text)
except:
raise
print(sha1_signatures)
mime = sys.argv[1]
new_signatures = defaultdict(dict)
new_signatures.update(sha1_signatures)
for filename in sys.argv[2:]:
print(f"parsing {filename}")
size, hash_string, name = parse(filename, mime)
print(f"{size} {hash_string} {mime} {name}")
new_signatures[size][hash_string] = (mime, name)
lines = []
lines.append("sha1_signatures = {")
for k,v in sorted(new_signatures.items()):
lines.append(f"{k}: {{")
for h,n in sorted(v.items(), key=lambda a:(a[1], a[0])):
lines.append(f" '{h}': {n},")
lines.append("},")
lines.append("} # end sha1_signatures")
print("\n".join(lines))
with open(source, 'w') as fh:
fh.write("\n".join(lines))