-
Notifications
You must be signed in to change notification settings - Fork 1
/
hiscoreanalysis.py
executable file
·222 lines (166 loc) · 8.11 KB
/
hiscoreanalysis.py
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
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
#!/usr/bin/python -tt
"""
MAME support program to analyze hiscores of a single game or a list of games:
- Binary hiscore data is readout and converted into ASCII code using the hi2txt Java archive.
- The hi2txt output is saved in a dedicated MAME hiscores directory.
- The top hiscore of each game is reformatted and saved in a formatted ASCII file (AMhiscores.ini). This file can be used to display the top hiscores in Attract-Mode.
Requirements:
- The latest hi2txt.jar and hi2txt.zip (see http://greatstone.free.fr/hi2txt/)
- The latest hiscore.dat (see http://highscore.mameworld.info/)
- Java (to run hi2txt.jar, see https://www.java.com)
Usage:
1) Change configsetup.py according to your system setup.
2) Create a ${MAMEconfigdir}/hi2txt/ directory and put hi2txt.jar and hi2txt.zip in this directory.
3) Unzip hi2txt.zip here and rename the unzipped directory "hi2txt_zip_contents".
4) Make sure hiscore.dat is located in your ${MAMEconfigdir}/dats/ directory.
5) To process a single game, type:
./hiscoreanalysis.py {game}
where {game} is the romname of the game (e.g. pacman)
OR to process all games in your Attract-Mode MAME romlist, type:
./hiscoreanalysis.py all
Author: Gordon Lim
Last Edit: 1 Feb 2018
"""
import configsetup
import os
import sys
import subprocess
def createhiscorefile(game):
print("--- Creating AM hiscore file for {}:".format(game))
# Check if unzipped hi2txt.zip contains game.xml file:
if not os.path.isfile(hi2txtzipdir + game + ".xml"):
print("------ hi2txt.zip does not contain {}.xml => the hiscores of this game have not been identified or decoded yet => EXIT1".format(game))
return 1
else:
print("------ hi2txt.zip contains {}.xml...".format(game))
# Check if nvram/game/ or hi/game.hi exists in MAME directory:
MAMEbinaryhiscorefile = configsetup.MAMEconfigdir
if os.path.isdir(MAMEbinaryhiscorefile + 'nvram/' + game):
MAMEbinaryhiscorefile += 'nvram/' + game
print("------ nvram/{}/ exists...".format(game))
elif os.path.isfile(MAMEbinaryhiscorefile + 'hi/' + game + '.hi'):
MAMEbinaryhiscorefile += 'hi/' + game + '.hi'
print("------ hi/{}.hi exists...".format(game))
else:
print("------ nvram/{0} nor hi/{0}.hi exists => this game has not been played yet => EXIT2".format(game))
return 2
# Run Java on hi2txt.jar and save output in MAME hiscores directory:
MAMEhiscorefilename = MAMEhiscoredir + game + ".txt"
MAMEhiscorefile = open(MAMEhiscorefilename, 'w')
command = ["java", "-jar", hi2txtdir + "hi2txt.jar", "-r", MAMEbinaryhiscorefile, "-hiscoredat", hiscoredat,
"-keep-field", 'RANK',
"-keep-field", 'SCORE',
"-keep-field", 'NAME']
subprocess.call(command, stdout=MAMEhiscorefile)
MAMEhiscorefile.close()
# Read temporary txt file containing hi2txt output and check hiscore table structure:
MAMEhiscorefile = open(MAMEhiscorefilename, "r")
firstline = MAMEhiscorefile.readline()
hiscoretablefields = firstline.rstrip('\n').split('|')
if (len(firstline) == 0):
print("------ hi2txt.jar output w.r.t. {} is empty => this game has been played but no hiscore has been saved in nvram or hi yet => EXIT3".format(game))
return 3
elif (len(hiscoretablefields) < 2):
print("------ Incompatible hiscore table format => EXIT4".format(game))
return 4
elif ((hiscoretablefields[0] != "RANK") and (hiscoretablefields[1] != "SCORE")):
print("------ Incompatible hiscore table format => EXIT5".format(game))
return 5
# Create hiscore list:
scores = []
for line in MAMEhiscorefile.readlines():
score = [field for field in line.rstrip('\n').split('|')]
if (len(score) < 2): # remove anomalous entries
continue
if (len(score) == 2): # add empty name for games like pacman, invaders, etc.
score.append(" ")
scores.append(score[0:3])
MAMEhiscorefile.close()
# Save top hiscore in AMhiscores.ini:
AMhiscorefilename = configsetup.AMsupportdir + "data/AMhiscores.ini"
AMhiscorefilename_exists = False
if os.path.isfile(AMhiscorefilename):
AMhiscorefilename_exists = True
AMhiscorefile = open(AMhiscorefilename, 'r')
lines = []
while True:
line = AMhiscorefile.readline()
if not line:
break
if (line == "[{}]\n".format(game)):
dummy = AMhiscorefile.readline() # skip score
dummy = AMhiscorefile.readline() # skip name
else:
lines.append(line)
AMhiscorefile.close()
AMhiscorefile = open(AMhiscorefilename, 'w')
if AMhiscorefilename_exists:
for line in lines:
AMhiscorefile.write(line)
AMhiscorefile.write("[{}]\n".format(game))
AMhiscorefile.write("score={}\n".format(scores[0][1]))
AMhiscorefile.write("name={}\n".format(scores[0][2]))
AMhiscorefile.close()
print("------ AM hiscore file for {} created => SUCCESS".format(game))
return 0
def main():
# Setup configuration:
configsetup.init()
global hi2txtdir
global hi2txtzipdir
global hiscoredat
global MAMEhiscoredir
hi2txtdir = configsetup.MAMEconfigdir + "hi2txt/"
hi2txtzipdir = hi2txtdir + "hi2txt_zip_contents/"
hiscoredat = configsetup.MAMEconfigdir + "dats/hiscore.dat"
MAMEhiscoredir = configsetup.MAMEconfigdir + "hiscores/"
if not os.path.isdir(hi2txtdir):
print("MAME hi2txt directory does not exist - EXIT")
return 1
if not os.path.isdir(hi2txtzipdir):
print("MAME hi2txt_zip_contents directory does not exist - EXIT")
return 1
if not os.path.isfile(hiscoredat):
print("MAME hiscore.dat does not exist - EXIT")
return 1
if not os.path.isdir(MAMEhiscoredir):
subprocess.call(["mkdir", "hiscores"], cwd = configsetup.MAMEconfigdir)
if not os.path.isdir(MAMEhiscoredir):
print("ERROR: AM hiscores directory does not exist - EXIT")
return 1
# Check input and process game(s):
clearasciihiscores = raw_input('Remove all ASCII hiscore files? (this will NOT delete binary hiscore data created by MAME in the nvram and hi directories) Press "y" or "n" followed by return/enter: ')
if not ((clearasciihiscores == 'y') or (clearasciihiscores == 'n')):
print("Next time please type 'y' or 'n'")
return 1
if (clearasciihiscores == 'y'):
subprocess.call('rm *.txt', cwd = MAMEhiscoredir, shell = True)
if (len(sys.argv) != 2):
print("Please provide a romname or 'all' as input argument")
return 1
inputargument = sys.argv[1]
if (inputargument == 'all'):
# Transform AM romlist into list of games:
games, header = configsetup.create_list_of_games_from_romlist()
if (len(games) == 0):
print("AM romlist is empty - EXIT")
return 1
# Create hiscore file for each game:
counts = [0, 0, 0, 0, 0, 0]
for game in games:
returncode = createhiscorefile(game[0])
counts[returncode] += 1
print("==> Return code '0' indicates a succesfully processed game")
print("--> Return code '1' indicates a hi2txt-incompatible game")
print("--> Return code '2' indicates a hi2txt-compatible game, but it has not been played yet")
print("--> Return code '3' indicates a hi2txt-compatible game that has been played, but no hiscore has been saved yet")
print("--> Return code '4' indicates a hi2txt-compatible game, but the hiscore table format is anomalous")
print("--> Return code '5' indicates a hi2txt-compatible game, but the hiscore table format is anomalous")
print("==> Total # of games = {}".format(sum(counts)))
for i in range(0, len(counts)):
print("--> # of return code '{}' games = {}".format(i, counts[i]))
else:
createhiscorefile(inputargument)
return 0
if __name__ == '__main__':
main()