283 lines
7.5 KiB
Python
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()
|