-
Notifications
You must be signed in to change notification settings - Fork 594
/
sfxconvert.py
167 lines (148 loc) · 4.96 KB
/
sfxconvert.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
#!/usr/bin/env python3
import os
import argparse
AudioFunctions = {}
Verbose = False
Verbose2 = False
def set_verbose(v):
global Verbose
global Verbose2
Verbose = v
Verbose2 = v
return 1
def make_audio_dict(AudioFunctions, repo):
with open(repo + os.sep + 'include' + os.sep + 'functions.h','r') as funcfile:
funcdata = funcfile.readlines()
for i, line in enumerate(funcdata):
if(line.count('sfxId')):
funcname, argnum = get_func_data(funcdata,i)
if(funcname != None):
AudioFunctions[funcname] = argnum
return 1
def get_func_data(funcdata,i):
j = i
while(funcdata[j - 1].count(';') == 0):
j -= 1
k = i + 1
while(funcdata[k - 1].count(';') == 0):
k += 1
prototype = "".join(funcdata[j:k])
argdata = prototype.replace('(',',').replace(')',',').split(',')
funcname = argdata[0].split(' ')[1]
for x in range(len(argdata)):
if(argdata[x].count('sfxId')):
break
if(x == len(argdata) - 1):
print('sfxId not found in ', funcname)
return None,-1
return funcname, x - 1
def lookup_sfx(idnum, repo):
if(type(idnum) is int):
id = '0x' + format(idnum,'X')
elif(idnum.isnumeric()):
id = '0x' + format(int(idnum),'X')
else:
id = idnum
idfix,sfxFlag = fix_sfx_flag(id)
with open(repo + os.sep + 'include' + os.sep + 'sfx.h','r') as sfxfile:
for line in sfxfile:
if(line.count(idfix)):
return line.split(' ')[1] + sfxFlag
return 'INVALID_ID'
def fix_sfx_flag(id):
if(id.endswith(' - SFX_FLAG')):
splitdata = id.split('-')
return splitdata[0].strip(), ' -' + splitdata[1]
if not(int(id,16) & 0x800):
newid = '0x' + format(int(id,16) + 0x800,'X')
sfxFlag = ' - SFX_FLAG'
else :
newid = id
sfxFlag = ''
return newid,sfxFlag
def fix_sfx_func(sourcedata, i, j, repo):
data = ''.join(sourcedata[i:j])
func = data.split('(')[0].strip()
index = data.find(func)
argnum = AudioFunctions.get(func,-1)
if(argnum == -1 or index == -1):
print('Function lookup error at line', i, 'in', func)
return -1
args = data[index:].replace('(',',').replace(')',',').split(',')
sfxId = args[argnum + 1].strip()
if(sfxId.count('NA_SE') != 0):
return 0
newId = lookup_sfx(sfxId, repo)
if(newId == 'INVALID_ID'):
print('ID parse error at line', i, 'in', func)
return -2
for k in range(i, j):
sourcedata[k] = sourcedata[k].replace(sfxId,newId)
if Verbose:
print('Replaced', sfxId, 'with', newId, 'in', func, 'at line', i + 1)
return 1
def find_audio_func(line):
audiofuncs = list(AudioFunctions.keys())
funcname = line.split('(')[0].strip()
for func in audiofuncs:
if(line.count(func)):
return func
return False
def fix_sfx_all(repo):
global Verbose2
tv = Verbose2
Verbose2 = False
for subdir, dirs, files in os.walk(repo + os.sep + 'src'):
for filename in files:
if(filename.endswith('.c')):
file = subdir + os.sep + filename
fix_sfx(file, repo)
Verbose2 = tv
return 1
def fix_sfx(file, repo, outfile = None):
if(outfile == None):
outfile = file
make_audio_dict(AudioFunctions, repo)
with open(file,'r',encoding='utf-8') as sourcefile:
sourcedata = sourcefile.readlines()
replacements = set()
j = 0
lookuperrors = 0
funcerrors = 0
iderrors = 0
fixes = 0
for i, line in enumerate(sourcedata):
if(i < j):
continue
if(find_audio_func(line)):
j = i
while(sourcedata[j].count(';') == 0):
j += 1
status = fix_sfx_func(sourcedata, i, j + 1, repo)
if(status == -2):
iderrors += 1
elif(status == -1):
lookuperrors += 1
elif(status > 0):
fixes += 1
if(fixes > 0):
with open(outfile,'w',encoding ='utf-8',newline='\n') as outfile:
outfile.writelines(sourcedata)
if Verbose:
print(file, 'updated')
elif Verbose2:
print('No changes made to', file)
if(lookuperrors > 0):
print('Problem with function lookup. Try formatting functions.h')
if(iderrors > 0):
print('Problem with id parsing. Make sure your SFX ids are in hex.')
return 1
parser = argparse.ArgumentParser(description='Convert hex SFX ids to macros')
parser.add_argument('file', help="source file to be processed")
parser.add_argument('repo', help="directory of the decomp repo")
parser.add_argument('-o', metavar='outfile',dest='outfile',help='file to write to instead of original')
parser.add_argument('-v', action='store_true',help='show what changes are made')
if __name__ == "__main__":
args = parser.parse_args()
set_verbose(args.v)
fix_sfx(args.file, args.repo, outfile=args.outfile)