2016-07-16 17:15:16 +02:00

283 lines
7.5 KiB
Python

import sqlite3
import os
import re
import string
import stat
import popen2
import glob
import sys
import pprint
# Detect Mirrord Roms
# Rom Type Mapping
#
# 0 ROM only
# 1 ROM and RAM
# 2 ROM and Save RAM
# 3 ROM and DSP1 chip
# 4 ROM, RAM and DSP1 chip
# 5 ROM, Save RAM and DSP1 chip
# 19 ROM and Super FX chip
# 227 ROM, RAM and GameBoy data
# 246 ROM and DSP2 chip
# Process /Users/david/Devel/arch/snes/roms/Teenage Mutant Ninja Turtles IV - Turtles in Time (U) [!].smc
# 0 uCON64 2.0.0 Apple (PPC) 1999-2005
# 1 Uses code from various people. See 'developers.html' for more!
# 2 This may be freely redistributed under the terms of the GNU Public License
# 4 /Users/david/Devel/arch/snes/roms/Teenage Mutant Ninja Turtles IV - Turtles in Time (U) [!].smc
# 6 Multi Game Doctor (2)/Multi Game Hunter/MGH
# 8 00007fb0 ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ff ........
# 9 00007fc0 54 2e 4d 2e 4e 2e 54 2e 20 34 20 20 20 20 20 20 T.M.N.T. 4
# 10 00007fd0 20 20 20 20 20 20 00 0a 00 01 a4 00 7c e9 83 16 ......|...
# 12 Super Nintendo Entertainment System/SNES/Super Famicom
# 13 T.M.N.T. 4
# 14 Konami
# 15 U.S.A.
# 16 1048576 Bytes (8.0000 Mb)
# 18 Padded: Maybe, 105 Bytes (0.0008 Mb)
# 19 Interleaved/Swapped: No
# 20 Backup unit/emulator header: No
# 21 HiROM: No
# 22 Internal size: 8 Mb
# 23 ROM type: (0) ROM
# 24 ROM speed: 200 ns (SlowROM)
# 25 SRAM: No
# 26 Version: 1.0
# 27 Checksum: Ok, 0x1683 (calculated) == 0x1683 (internal)
# 28 Inverse checksum: Ok, 0xe97c (calculated) == 0xe97c (internal)
# 29 Checksum (CRC32): 0x5940bd99
# 31 This ROM has no backup unit header
swc_header_tpl = '''
Backup unit header info (SWC)
00000000 20 00 0c 00 00 00 00 00 aa bb 04 00 00 00 00 00 ...............
00000010 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
00000020 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 00 ................
[0-1] File size: 262144 Bytes (2.0000 Mb) => Matches
[2:7] Run program in mode: 3
[2:6] Split: No => Matches
[2:5] SRAM mapping mode: LoROM => Matches
[2:4] DRAM mapping mode: LoROM => Matches
[2:3-2] SRAM size: 0 kB => Matches
[2:1] Run program in mode: 3
[2:0] External cartridge memory: Disabled
'''
def createdb():
try:
os.unlink("roms.sqlite3")
except:
pass
conn = sqlite3.connect('roms.sqlite3')
c = conn.cursor()
c.execute('''create table roms
(
file_name text,
file_ext text,
file_size integer,
rom_size integer,
rom_mb real,
rom_padded integer,
rom_trainer integer,
rom_backup integer,
rom_name text,
rom_vendor text,
rom_region text,
rom_hirom integer,
rom_internalsize integer,
rom_type integer,
rom_speed integer,
rom_sram integer,
rom_version real,
rom_chk integer,
swc_size integer,
swc_mode integer,
swc_split text,
swc_sram_mode text,
swc_dram_mode text,
swc_sram_size text
)''')
return conn, c
def process(conn, c, file_name, out):
file_ext = os.path.splitext(file_name)[1].replace(".", '')
file_size = os.stat(file_name)[stat.ST_SIZE]
rom_size = 0
rom_mb = 0
rom_padded = 0
rom_trainer = 0
rom_backup = 0
rom_name = ''
rom_vendor = ''
rom_region = ''
rom_hirom = 0
rom_internalsize = 0
rom_type = 0
rom_speed = 0
rom_sram = 0
rom_version = 0
rom_chk = 0
swc_size = 0
swc_mode = 0
swc_split = ''
swc_sram_mode = ''
swc_dram_mode = ''
swc_sram_size = ''
print "-" * 60
print "Process %s" % file_name
try:
rom_name = out[13]
rom_vendor = out[14]
rom_region = out[15]
try:
rom_size = int(out[16].split(" ")[0])
rom_mb = float(
re.compile("([\d.]+) Mb").search(out[16]).groups()[0])
except:
print "Broken..."
return
if not "No" in out[18]:
rom_padded = int(
re.compile("([\d.]+) Bytes").search(out[18]).groups()[0])
for idx, line in enumerate(out):
if line is None:
continue
if "Backup unit/emulator header: Yes" in line:
rom_backup = int(
re.compile("([\d.]+) Bytes").search(line).groups()[0])
if "Intro/Trainer:" in line:
rom_trainer = int(
re.compile("([\d.]+) Bytes").search(line).groups()[0])
if "HiROM: Yes" in line:
rom_hirom = 1
if "Internal size:" in line:
rom_internalsize = int(
re.compile("([\d.]+) Mb").search(line).groups()[0])
if "ROM type:" in line:
try:
rom_type = int(
re.compile("([\d]+)").search(line).groups()[0])
except:
pass
if "ROM speed:" in line:
rom_speed = int(
re.compile("([\d]+) ns").search(line).groups()[0])
if "SRAM: Yes" in line:
rom_sram = int(
re.compile("([\d]+) kBytes").search(line).groups()[0])
if "Version:" in line:
rom_version = float(
re.compile("([\d.]+)").search(line).groups()[0])
if "Checksum: Ok" in line:
rom_chk = 1
except:
for idx, line in enumerate(out):
if line is None:
continue
print idx, line
sys.exit()
query = """INSERT INTO roms
VALUES
(
?,?,?,?,?,
?,?,?,?,?,
?,?,?,?,?,
?,?,?,?,?,
?,?,?,?) """
data = (file_name,
file_ext,
file_size,
rom_size,
rom_mb,
rom_padded,
rom_trainer,
rom_backup,
rom_name,
rom_vendor,
rom_region,
rom_hirom,
rom_internalsize,
rom_type,
rom_speed,
rom_sram,
rom_version,
rom_chk,
swc_size,
swc_mode,
swc_split,
swc_sram_mode,
swc_dram_mode,
swc_sram_size)
c.execute(query, data)
conn.commit()
def ucon64_info(filename):
cmd = "ucon64 --dbuh -snes \"%s\"" % filename
r, w, e = popen2.popen3(cmd)
err = e.readlines()
out = r.readlines()
r.close()
e.close()
w.close()
if len(err):
return False, err
return out, err
def clean(s):
s = s.replace("\n", "")
if not len(s):
return None
return s
def main():
conn, c = createdb()
path = sys.argv[1]
files = glob.glob(path + "/*")
for filename in files:
try:
r, err = ucon64_info(filename)
if not r:
print err
continue
r = map(clean, r)
process(conn, c, filename, r)
except (KeyboardInterrupt, SystemExit):
print "Saving DB..."
c.close()
conn.commit()
conn.close()
sys.exit(-1)
c.close()
conn.commit()
conn.close()
if __name__ == "__main__":
main()