mirror of
https://github.com/robmcmullen/atrcopy.git
synced 2024-11-29 11:51:14 +00:00
Added magic signature detection
* appends detail to MIME type if match; e.g. application/vnd.atari8bit.atr.jumpman
This commit is contained in:
parent
b1e7aff40b
commit
2b95276029
@ -24,6 +24,7 @@ from .segments import SegmentData, SegmentSaver, DefaultSegment, EmptySegment, O
|
|||||||
from .spartados import SpartaDosDiskImage
|
from .spartados import SpartaDosDiskImage
|
||||||
from .cartridge import A8CartHeader, AtariCartImage
|
from .cartridge import A8CartHeader, AtariCartImage
|
||||||
from .parsers import SegmentParser, DefaultSegmentParser, guess_parser_for_mime, guess_parser_for_system, iter_parsers, iter_known_segment_parsers, mime_parse_order, parsers_for_filename
|
from .parsers import SegmentParser, DefaultSegmentParser, guess_parser_for_mime, guess_parser_for_system, 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 .utils import to_numpy, text_to_int
|
||||||
|
|
||||||
|
|
||||||
@ -70,6 +71,9 @@ def find_diskimage(filename):
|
|||||||
continue
|
continue
|
||||||
if options.verbose:
|
if options.verbose:
|
||||||
print("Found parser %s" % parser.menu_name)
|
print("Found parser %s" % parser.menu_name)
|
||||||
|
mime2 = guess_detail_for_mime(mime, rawdata, parser)
|
||||||
|
if mime != mime2 and options.verbose:
|
||||||
|
print("Signature match: %s" % mime2)
|
||||||
break
|
break
|
||||||
if parser is None:
|
if parser is None:
|
||||||
print("%s: Unknown disk image type" % filename)
|
print("%s: Unknown disk image type" % filename)
|
||||||
|
73
atrcopy/magic.py
Normal file
73
atrcopy/magic.py
Normal file
@ -0,0 +1,73 @@
|
|||||||
|
import numpy as np
|
||||||
|
|
||||||
|
import logging
|
||||||
|
log = logging.getLogger(__name__)
|
||||||
|
|
||||||
|
|
||||||
|
magic = [
|
||||||
|
{'mime': "application/vnd.atari8bit.atr.getaway_pd",
|
||||||
|
'name': "Getaway Public Domain ATR",
|
||||||
|
'signature': [
|
||||||
|
(slice(8, 10), [0x82, 0x39]),
|
||||||
|
(slice(12, 16), [0x67, 0x21, 0x70, 0x64]),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{'mime': "application/vnd.atari8bit.xex.getaway",
|
||||||
|
'name': "Getaway XEX",
|
||||||
|
'signature': [
|
||||||
|
(slice(0, 6), [0xff, 0xff, 0x80, 0x2a, 0xff, 0x8a]),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{'mime': "application/vnd.atari8bit.atr.getaway",
|
||||||
|
'name': "Getaway ATR",
|
||||||
|
'signature': [
|
||||||
|
(slice(0x10, 0x19), [0x00, 0xc1, 0x80, 0x0f, 0xcc, 0x22, 0x18, 0x60, 0x0e]),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{'mime': "application/vnd.atari8bit.atr.jumpman_level_tester",
|
||||||
|
'name': "Jumpman Level Tester from Omnivore",
|
||||||
|
'signature': [
|
||||||
|
(slice(0, 5), [0x96, 0x02 , 0xd0 , 0x05 , 0x80]),
|
||||||
|
(0x0196 + 0x3f, 0x4c),
|
||||||
|
(0x0196 + 0x48, 0x20),
|
||||||
|
(0x0196 + 0x4b, 0x60),
|
||||||
|
(0x0196 + 0x4c, 0xff),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
|
||||||
|
{'mime': "application/vnd.atari8bit.atr.jumpman",
|
||||||
|
'name': "Jumpman",
|
||||||
|
'signature': [
|
||||||
|
(slice(0, 5), [0x96, 0x02 , 0x80 , 0x16 , 0x80]),
|
||||||
|
(0x0810 + 0x3f, 0x4c),
|
||||||
|
(0x0810 + 0x48, 0x20),
|
||||||
|
(0x0810 + 0x4b, 0x60),
|
||||||
|
(0x0810 + 0x4c, 0xff),
|
||||||
|
],
|
||||||
|
},
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
def check_signature(raw, sig):
|
||||||
|
for index, expected in sig:
|
||||||
|
actual = raw.data[index].tolist()
|
||||||
|
if actual == expected:
|
||||||
|
log.debug(" match at %s: %s" % (str(index), str(expected)))
|
||||||
|
if actual != expected:
|
||||||
|
log.debug(" failed at %s: %s != %s" % (str(index), str(expected), str(raw.data[index])))
|
||||||
|
return False
|
||||||
|
return True
|
||||||
|
|
||||||
|
|
||||||
|
def guess_detail_for_mime(mime, raw, parser):
|
||||||
|
for entry in magic:
|
||||||
|
if entry['mime'].startswith(mime):
|
||||||
|
log.debug("checking signature for %s" % entry['mime'])
|
||||||
|
if check_signature(raw, entry['signature']):
|
||||||
|
log.debug("found signature: %s" % entry['name'])
|
||||||
|
return entry['mime']
|
||||||
|
return mime
|
||||||
|
|
@ -12,6 +12,7 @@ from .mame import MameZipImage
|
|||||||
from .dos33 import Dos33DiskImage, ProdosDiskImage, Dos33BinFile
|
from .dos33 import Dos33DiskImage, ProdosDiskImage, Dos33BinFile
|
||||||
from .standard_delivery import StandardDeliveryImage
|
from .standard_delivery import StandardDeliveryImage
|
||||||
from .errors import *
|
from .errors import *
|
||||||
|
from .magic import guess_detail_for_mime
|
||||||
|
|
||||||
import logging
|
import logging
|
||||||
log = logging.getLogger(__name__)
|
log = logging.getLogger(__name__)
|
||||||
@ -178,6 +179,7 @@ def guess_parser_for_system(mime_base, r):
|
|||||||
if mime.startswith(mime_base):
|
if mime.startswith(mime_base):
|
||||||
p = guess_parser_for_mime(mime, r)
|
p = guess_parser_for_mime(mime, r)
|
||||||
if p is not None:
|
if p is not None:
|
||||||
|
mime = guess_detail_for_mime(mime, r, p)
|
||||||
return mime, p
|
return mime, p
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
@ -186,6 +188,7 @@ def iter_parsers(r):
|
|||||||
for mime in mime_parse_order:
|
for mime in mime_parse_order:
|
||||||
p = guess_parser_for_mime(mime, r)
|
p = guess_parser_for_mime(mime, r)
|
||||||
if p is not None:
|
if p is not None:
|
||||||
|
mime = guess_detail_for_mime(mime, r, p)
|
||||||
return mime, p
|
return mime, p
|
||||||
return None, None
|
return None, None
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user