summaryrefslogtreecommitdiffstatshomepage
path: root/scripts/minimaws/minimaws.py
blob: bf28d6d649d83e229c44aeadb7978b08c646070e (plain) (blame)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
#!/usr/bin/python
##
## license:BSD-3-Clause
## copyright-holders:Vas Crabb
##
## Demonstrates use of MAME's XML system information output
##
## This script requires Python 2.7 or Python 3.4, and SQLite 3.6.19 at
## the very least.  Help is provided for all command-line options (use
## -h or --help).
##
## Before you can use the scripts, you need to load MAME system
## information into a database:
##
## $ python minimaws.py load --executable path/to/mame
##
## (The script uses the name "minimaws.sqlite3" for the database by
## default, but you can override this with the --database option.)
##
## After you've loaded the database, you can use query commands.  Most
## of the query commands behave similarly to MAME's auxiliary verbs but
## case-sensitive and with better globbing (output not shown for
## brevity):
##
## $ python minimaws.py listfull "unkch*"
## $ python minimaws.py listclones "unkch*"
## $ python minimaws.py listbrothers superx
##
## The romident command does not support archives or software lists, but
## it's far faster than using MAME as it has optimised indexes, and
## results are grouped by machine rather than by file:
##
## $ python minimaws.py romident 27c64.bin dump-dir
##
## One more sophisticated query command is provided that MAME has no
## equivalent for.  The listaffected command shows all runnable machines
## that reference devices defined in specified source files:
##
## $ python minimaws.py listaffected "src/devices/cpu/m6805/*" src/devices/cpu/mcs40/mcs40.cpp
##
## This script can also run a local web server allowing you to explore
## systems, devices and source files:
##
## $ python minimaws.py serve
##
## The default TCP port is 8080 but if desired, this can be changed with
## the --port option.  The web service is implemented using WSGI, so it
## can be run in a web server if desired (e.g. using Apache mod_wsgi).
## It uses get queries and provides cacheable reponses, so it should
## work behind a caching proxy (e.g. squid or nginx).  Although the
## service is written to avoid SQL injected and directory traversal
## attacks, and it avoids common sources of security issues, it has not
## been audited for vulnerabilities and is not recommended for use on
## public web sites.
##
## To use the web service, you need to know the short name of a device/
## system, or the name of a source file containing a system:
##
## http://localhost:8080/machine/intlc440
## http://localhost:8080/machine/a2mouse
## http://localhost:8080/sourcefile/src/devices/cpu/m68000/m68kcpu.cpp
##
## You can also start with a list of all source files containing machine
## definitions, but this is quite a large page and may perform poorly:
##
## http://localhost:8080/sourcefile/
##
## One feature that may be of iterest to front-end authors or users of
## computer emulation is the ability to show available slot options and
## update live as changes are made.  This can be seen in action on
## computer systems:
##
## http://localhost:8080/machine/ibm5150
## http://localhost:8080/machine/apple2e
## http://localhost:8080/machine/ti82
##
## On any of these, and many other systems, you can select slot options
## and see dependent slots update.  Required command-line arguments to
## produce the selected configuration are also displayed.

import lib.auxverbs
import lib.lxparse
import lib.wsgiserve

import argparse
import sys


if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument('--database', metavar='<dbfile>', default='minimaws.sqlite3', help='SQLite 3 info database file (defaults to minimaws.sqlite3)')
    subparsers = parser.add_subparsers(title='commands', dest='command', metavar='<command>')

    subparser = subparsers.add_parser('listfull', help='list short names and full names')
    subparser.add_argument('pattern', nargs='?', metavar='<pat>', help='short name glob pattern')

    subparser = subparsers.add_parser('listsource', help='list short names and source files')
    subparser.add_argument('pattern', nargs='?', metavar='<pat>', help='short name glob pattern')

    subparser = subparsers.add_parser('listclones', help='show clones')
    subparser.add_argument('pattern', nargs='?', metavar='<pat>', help='short name/parent glob pattern')

    subparser = subparsers.add_parser('listbrothers', help='show drivers from the same source file(s)')
    subparser.add_argument('pattern', nargs='?', metavar='<pat>', help='short name glob pattern')

    subparser = subparsers.add_parser('listaffected', help='show drivers affected by source change(s)')
    subparser.add_argument('pattern', nargs='+', metavar='<pat>', help='source file glob pattern')

    subparser = subparsers.add_parser('romident', help='identify ROM dump(s)')
    subparser.add_argument('path', nargs='+', metavar='<path>', help='ROM dump file/directory path')

    subparser = subparsers.add_parser('serve', help='serve over HTTP')
    subparser.add_argument('--port', metavar='<port>', default=8080, type=int, help='server TCP port')
    subparser.add_argument('--host', metavar='<host>', default='', help='server TCP hostname')

    subparser = subparsers.add_parser('load', help='load machine information')
    group = subparser.add_mutually_exclusive_group(required=True)
    group.add_argument('--executable', metavar='<exe>', help='emulator executable')
    group.add_argument('--file', metavar='<xmlfile>', help='XML machine information file')

    options = parser.parse_args()
    if options.command == 'listfull':
        lib.auxverbs.do_listfull(options)
    elif options.command == 'listsource':
        lib.auxverbs.do_listsource(options)
    elif options.command == 'listclones':
        lib.auxverbs.do_listclones(options)
    elif options.command == 'listbrothers':
        lib.auxverbs.do_listbrothers(options)
    elif options.command == 'listaffected':
        lib.auxverbs.do_listaffected(options)
    elif options.command == 'romident':
        lib.auxverbs.do_romident(options)
    elif options.command == 'serve':
        lib.wsgiserve.run_server(options)
    elif options.command == 'load':
        lib.lxparse.load_info(options)