Farewell_
afaf54cfdb
I used to rely on musicinfo.bin to build the songlist, Now using all files to build an expected song database
561 lines
19 KiB
Python
561 lines
19 KiB
Python
from argparse import ArgumentParser
|
|
from enum import Enum
|
|
import json
|
|
|
|
from helpers import (
|
|
doesPathExist,
|
|
findAllObjects,
|
|
findDoubloninList,
|
|
findKeyInList,
|
|
isChn,
|
|
loadFile,
|
|
)
|
|
|
|
if __name__ == "__main__":
|
|
parser = ArgumentParser()
|
|
parser.add_argument(
|
|
"-l",
|
|
"--language",
|
|
default="englishUsText",
|
|
help="This sets the language used for sorting the files. Possible values are : japaneseText, englishUsText, chineseTText, chineseSText and koreanText",
|
|
)
|
|
|
|
args = parser.parse_args()
|
|
language = args.language
|
|
|
|
if language not in [
|
|
"japaneseText",
|
|
"englishUsText",
|
|
"chineseTText",
|
|
"chineseSText",
|
|
"koreanText",
|
|
]:
|
|
print(
|
|
"Invalid language, Possible values are : japaneseText, englishUsText, chineseTText, chineseSText and koreanText"
|
|
)
|
|
exit(1)
|
|
|
|
isChn = isChn()
|
|
songs = []
|
|
|
|
# region Loading files
|
|
checkFile = {}
|
|
|
|
infos = loadFile(path="./Data/x64/datatable/musicinfo.bin")
|
|
usbs = loadFile(path="./Data/x64/datatable/music_usbsetting.bin")
|
|
orders = loadFile(path="./Data/x64/datatable/music_order.bin")
|
|
attributes = loadFile(path="./Data/x64/datatable/music_attribute.bin")
|
|
words = loadFile(path="./Data/x64/datatable/wordlist.bin")
|
|
# endregion
|
|
|
|
|
|
# region Classes And Methods
|
|
class Genres(Enum):
|
|
Unknown = -1
|
|
Pop = 0
|
|
Anime = 1
|
|
Kids = 2
|
|
Vocaloid = 3
|
|
GameMusic = 4
|
|
NamcoOriginal = 5
|
|
Variety = 6 if isChn else 7
|
|
Classical = 7 if isChn else 8
|
|
if not isChn:
|
|
Custom = 9
|
|
|
|
@classmethod
|
|
def _missing_(cls, value):
|
|
return cls.Unknown
|
|
|
|
|
|
def initCheckFile():
|
|
global checkFile
|
|
checkFile = {
|
|
"stats": {
|
|
"TotalSongs": 0,
|
|
"MaxId": 0,
|
|
"UniqueIdTooHigh": 0,
|
|
"UniqueIdTooHighList": [],
|
|
"UnusedUniqueIds": 0,
|
|
"UnusedUniqueIdsList": [],
|
|
},
|
|
}
|
|
|
|
if infos is not None:
|
|
checkFile["musicinfo.bin"] = {
|
|
"TotalEntries": len(infos),
|
|
"Missing": 0,
|
|
"MissingList": [],
|
|
"Doublons": 0,
|
|
"DoublonsList": [],
|
|
"GenreNoList": [],
|
|
}
|
|
for song in infos:
|
|
name = findKeyInList(
|
|
list=words,
|
|
key="key",
|
|
keyValue="song_" + song["id"],
|
|
value=language,
|
|
)
|
|
sub = findKeyInList(
|
|
list=words,
|
|
key="key",
|
|
keyValue="song_sub_" + song["id"],
|
|
value=language,
|
|
)
|
|
detail = findKeyInList(
|
|
list=words,
|
|
key="key",
|
|
keyValue="song_detail_" + song["id"],
|
|
value=language,
|
|
)
|
|
|
|
songs.append(
|
|
{
|
|
"id": song["id"],
|
|
"uniqueId": song["uniqueId"],
|
|
"genreNo": song["genreNo"],
|
|
"name": name,
|
|
"sub": sub,
|
|
"detail": detail,
|
|
}
|
|
)
|
|
|
|
if attributes is not None:
|
|
checkFile["music_attribute.bin"] = {
|
|
"TotalEntries": len(attributes),
|
|
"Missing": 0,
|
|
"MissingList": [],
|
|
"Mismatch": 0,
|
|
"MismatchList": [],
|
|
"Doublons": 0,
|
|
"DoublonsList": [],
|
|
}
|
|
for song in attributes:
|
|
temp = findKeyInList(list=songs, key="id", keyValue=song["id"])
|
|
if temp is not None:
|
|
continue
|
|
|
|
name = findKeyInList(
|
|
list=words,
|
|
key="key",
|
|
keyValue="song_" + song["id"],
|
|
value=language,
|
|
)
|
|
sub = findKeyInList(
|
|
list=words,
|
|
key="key",
|
|
keyValue="song_sub_" + song["id"],
|
|
value=language,
|
|
)
|
|
detail = findKeyInList(
|
|
list=words,
|
|
key="key",
|
|
keyValue="song_detail_" + song["id"],
|
|
value=language,
|
|
)
|
|
genreNo = findKeyInList(
|
|
list=infos,
|
|
key="id",
|
|
keyValue=song["id"],
|
|
value="genreNo",
|
|
)
|
|
|
|
songs.append(
|
|
{
|
|
"id": song["id"],
|
|
"uniqueId": song["uniqueId"],
|
|
"genreNo": genreNo,
|
|
"name": name,
|
|
"sub": sub,
|
|
"detail": detail,
|
|
}
|
|
)
|
|
|
|
if orders is not None:
|
|
checkFile["music_order.bin"] = {
|
|
"TotalEntries": len(orders),
|
|
"UniqueEntries": 0,
|
|
"UniqueEntriesList": [],
|
|
"GenreNoList": [],
|
|
"Missing": 0,
|
|
"MissingList": [],
|
|
"Mismatch": 0,
|
|
"MismatchList": [],
|
|
}
|
|
for song in orders:
|
|
temp = findKeyInList(list=songs, key="id", keyValue=song["id"])
|
|
if temp is not None:
|
|
continue
|
|
|
|
name = findKeyInList(
|
|
list=words,
|
|
key="key",
|
|
keyValue="song_" + song["id"],
|
|
value=language,
|
|
)
|
|
sub = findKeyInList(
|
|
list=words,
|
|
key="key",
|
|
keyValue="song_sub_" + song["id"],
|
|
value=language,
|
|
)
|
|
detail = findKeyInList(
|
|
list=words,
|
|
key="key",
|
|
keyValue="song_detail_" + song["id"],
|
|
value=language,
|
|
)
|
|
genreNo = findKeyInList(
|
|
list=infos,
|
|
key="id",
|
|
keyValue=song["id"],
|
|
value="genreNo",
|
|
)
|
|
|
|
songs.append(
|
|
{
|
|
"id": song["id"],
|
|
"uniqueId": song["uniqueId"],
|
|
"genreNo": genreNo,
|
|
"name": name,
|
|
"sub": sub,
|
|
"detail": detail,
|
|
}
|
|
)
|
|
|
|
if usbs is not None:
|
|
checkFile["music_usbsetting.bin"] = {
|
|
"TotalEntries": len(usbs),
|
|
"Missing": 0,
|
|
"MissingList": [],
|
|
"Mismatch": 0,
|
|
"MismatchList": [],
|
|
"Doublons": 0,
|
|
"DoublonsList": [],
|
|
}
|
|
for song in usbs:
|
|
temp = findKeyInList(list=songs, key="id", keyValue=song["id"])
|
|
if temp is not None:
|
|
continue
|
|
|
|
name = findKeyInList(
|
|
list=words,
|
|
key="key",
|
|
keyValue="song_" + song["id"],
|
|
value=language,
|
|
)
|
|
sub = findKeyInList(
|
|
list=words,
|
|
key="key",
|
|
keyValue="song_sub_" + song["id"],
|
|
value=language,
|
|
)
|
|
detail = findKeyInList(
|
|
list=words,
|
|
key="key",
|
|
keyValue="song_detail_" + song["id"],
|
|
value=language,
|
|
)
|
|
genreNo = findKeyInList(
|
|
list=infos,
|
|
key="id",
|
|
keyValue=song["id"],
|
|
value="genreNo",
|
|
)
|
|
|
|
songs.append(
|
|
{
|
|
"id": song["id"],
|
|
"uniqueId": song["uniqueId"],
|
|
"genreNo": genreNo,
|
|
"name": name,
|
|
"sub": sub,
|
|
"detail": detail,
|
|
}
|
|
)
|
|
|
|
if words is not None:
|
|
checkFile["wordlist.bin"] = {
|
|
"TotalEntries": len(words),
|
|
"MissingSongName": 0,
|
|
"MissingSongNameList": [],
|
|
"MissingSongSub": 0,
|
|
"MissingSongSubList": [],
|
|
"MissingSongDetail": 0,
|
|
"MissingSongDetailList": [],
|
|
"Doublons": 0,
|
|
"DoublonsList": [],
|
|
}
|
|
|
|
if all([doesPathExist("./Data/x64/fumen"), doesPathExist("./Data/x64/sound")]):
|
|
checkFile.update(
|
|
{
|
|
"GameFiles": {
|
|
"MissingSound": 0,
|
|
"MissingSoundList": [],
|
|
"MissingFumen": 0,
|
|
"MissingFumenList": [],
|
|
},
|
|
}
|
|
)
|
|
|
|
# Update stats
|
|
checkFile["stats"]["TotalSongs"] = len(songs)
|
|
checkFile["stats"]["MaxId"] = max(songs, key=lambda ev: ev["uniqueId"])["uniqueId"]
|
|
|
|
print("Found a total of", str(len(songs)), "songs in datatables")
|
|
|
|
|
|
# endregion
|
|
|
|
|
|
# Preparing the json file containing the results of this checking script
|
|
initCheckFile()
|
|
|
|
# Checking...
|
|
for song in songs:
|
|
# stats
|
|
# Checking for too high of an id
|
|
if song["uniqueId"] > 1599:
|
|
checkFile["stats"]["UniqueIdTooHigh"] += 1
|
|
checkFile["stats"]["UniqueIdTooHighList"].append(
|
|
{
|
|
"id": song["id"],
|
|
"uniqueId": song["uniqueId"],
|
|
}
|
|
)
|
|
|
|
# musicinfo.bin
|
|
if infos is not None:
|
|
# Check for missing uniqueIds or id and uniqueId mismatches
|
|
orderOccurences = findAllObjects(list=infos, key="id", keyValue=song["id"])
|
|
if len(orderOccurences) == 0:
|
|
checkFile["musicinfo.bin"]["Missing"] += 1
|
|
checkFile["musicinfo.bin"]["MissingList"].append(song["id"])
|
|
# Listing genres and counting entries for each genres
|
|
genre = {
|
|
"GenreNo": song["genreNo"],
|
|
"Name": Genres(song["genreNo"]).name,
|
|
"NumberofSongs": 0,
|
|
}
|
|
if (
|
|
findKeyInList(
|
|
list=checkFile["musicinfo.bin"]["GenreNoList"],
|
|
key="GenreNo",
|
|
keyValue=song["genreNo"],
|
|
)
|
|
is None
|
|
):
|
|
genre["NumberofSongs"] = len(
|
|
findAllObjects(list=infos, key="genreNo", keyValue=song["genreNo"])
|
|
)
|
|
checkFile["musicinfo.bin"]["GenreNoList"].append(genre)
|
|
# Search doublons
|
|
if findDoubloninList(list=infos, key="id", keyValue=song["id"]):
|
|
if song["id"] not in checkFile["musicinfo.bin"]["DoublonsList"]:
|
|
checkFile["musicinfo.bin"]["Doublons"] += 1
|
|
checkFile["musicinfo.bin"]["DoublonsList"].append(song["id"])
|
|
|
|
if findDoubloninList(list=infos, key="uniqueId", keyValue=song["uniqueId"]):
|
|
if song["uniqueId"] not in checkFile["musicinfo.bin"]["DoublonsList"]:
|
|
checkFile["musicinfo.bin"]["Doublons"] += 1
|
|
checkFile["musicinfo.bin"]["DoublonsList"].append(song["uniqueId"])
|
|
|
|
# music_attribute.bin
|
|
if attributes is not None:
|
|
# Check for missing uniqueIds or id and uniqueId mismatches
|
|
orderOccurences = findAllObjects(list=attributes, key="id", keyValue=song["id"])
|
|
if len(orderOccurences) == 0:
|
|
checkFile["music_attribute.bin"]["Missing"] += 1
|
|
checkFile["music_attribute.bin"]["MissingList"].append(song["id"])
|
|
else:
|
|
for occurence in orderOccurences:
|
|
if not all(
|
|
[
|
|
song["id"] == occurence["id"],
|
|
song["uniqueId"] == occurence["uniqueId"],
|
|
]
|
|
):
|
|
if (
|
|
song["id"]
|
|
not in checkFile["music_attribute.bin"]["MismatchList"]
|
|
):
|
|
checkFile["music_attribute.bin"]["Mismatch"] += 1
|
|
checkFile["music_attribute.bin"]["MismatchList"].append(
|
|
{
|
|
"id": song["id"],
|
|
"ExpectedUniqueId": song["uniqueId"],
|
|
"CurrentUniqueId": occurence["uniqueId"],
|
|
}
|
|
)
|
|
if findDoubloninList(list=attributes, key="id", keyValue=song["id"]):
|
|
if song["id"] not in checkFile["music_attribute.bin"]["DoublonsList"]:
|
|
checkFile["music_attribute.bin"]["Doublons"] += 1
|
|
checkFile["music_attribute.bin"]["DoublonsList"].append(song["id"])
|
|
if findDoubloninList(
|
|
list=attributes, key="uniqueId", keyValue=song["uniqueId"]
|
|
):
|
|
if song["uniqueId"] not in checkFile["musicinfo.bin"]["DoublonsList"]:
|
|
checkFile["music_attribute.bin"]["Doublons"] += 1
|
|
checkFile["music_attribute.bin"]["DoublonsList"].append(
|
|
song["uniqueId"]
|
|
)
|
|
|
|
# music_usbsetting.bin
|
|
if usbs is not None:
|
|
# Check for missing uniqueIds or id and uniqueId mismatches
|
|
orderOccurences = findAllObjects(list=usbs, key="id", keyValue=song["id"])
|
|
if len(orderOccurences) == 0:
|
|
checkFile["music_usbsetting.bin"]["Missing"] += 1
|
|
checkFile["music_usbsetting.bin"]["MissingList"].append(song["id"])
|
|
else:
|
|
for occurence in orderOccurences:
|
|
if not all(
|
|
[
|
|
song["id"] == occurence["id"],
|
|
song["uniqueId"] == occurence["uniqueId"],
|
|
]
|
|
):
|
|
if (
|
|
song["id"]
|
|
not in checkFile["music_usbsetting.bin"]["MismatchList"]
|
|
):
|
|
checkFile["music_usbsetting.bin"]["Mismatch"] += 1
|
|
checkFile["music_usbsetting.bin"]["MismatchList"].append(
|
|
{
|
|
"id": song["id"],
|
|
"ExpectedUniqueId": song["uniqueId"],
|
|
"CurrentUniqueId": occurence["uniqueId"],
|
|
}
|
|
)
|
|
|
|
# Search doublons
|
|
if findDoubloninList(list=usbs, key="id", keyValue=song["id"]):
|
|
if song["id"] not in checkFile["music_usbsetting.bin"]["DoublonsList"]:
|
|
checkFile["music_usbsetting.bin"]["Doublons"] += 1
|
|
checkFile["music_usbsetting.bin"]["DoublonsList"].append(song["id"])
|
|
if findDoubloninList(list=usbs, key="uniqueId", keyValue=song["uniqueId"]):
|
|
if song["uniqueId"] not in checkFile["musicinfo.bin"]["DoublonsList"]:
|
|
checkFile["music_usbsetting.bin"]["Doublons"] += 1
|
|
checkFile["music_usbsetting.bin"]["DoublonsList"].append(
|
|
song["uniqueId"]
|
|
)
|
|
|
|
# music_order.bin
|
|
if orders is not None:
|
|
# Check for missing uniqueIds or id and uniqueId mismatches
|
|
orderOccurences = findAllObjects(list=orders, key="id", keyValue=song["id"])
|
|
if len(orderOccurences) == 0:
|
|
checkFile["music_order.bin"]["Missing"] += 1
|
|
checkFile["music_order.bin"]["MissingList"].append(song["id"])
|
|
else:
|
|
songGenres = []
|
|
for occurence in orderOccurences:
|
|
songGenres.append(occurence["genreNo"])
|
|
if not all(
|
|
[
|
|
song["id"] == occurence["id"],
|
|
song["uniqueId"] == occurence["uniqueId"],
|
|
]
|
|
):
|
|
if song["id"] not in checkFile["music_order.bin"]["MismatchList"]:
|
|
checkFile["music_order.bin"]["Mismatch"] += 1
|
|
checkFile["music_order.bin"]["MismatchList"].append(
|
|
{
|
|
"id": song["id"],
|
|
"ExpectedUniqueId": song["uniqueId"],
|
|
"CurrentUniqueId": occurence["uniqueId"],
|
|
}
|
|
)
|
|
|
|
# Counting unique entries
|
|
checkFile["music_order.bin"]["UniqueEntries"] += 1
|
|
checkFile["music_order.bin"]["UniqueEntriesList"].append(
|
|
{
|
|
song["id"]: songGenres,
|
|
}
|
|
)
|
|
|
|
# wordlist.bin
|
|
if words is not None:
|
|
if song["name"] == "":
|
|
checkFile["wordlist.bin"]["MissingSongName"] += 1
|
|
checkFile["wordlist.bin"]["MissingSongNameList"].append(song["id"])
|
|
if song["sub"] == "":
|
|
checkFile["wordlist.bin"]["MissingSongSub"] += 1
|
|
checkFile["wordlist.bin"]["MissingSongSubList"].append(song["id"])
|
|
if song["detail"] == "":
|
|
checkFile["wordlist.bin"]["MissingSongDetail"] += 1
|
|
checkFile["wordlist.bin"]["MissingSongDetailList"].append(song["id"])
|
|
|
|
# Gamefiles
|
|
if all([doesPathExist("./Data/x64/fumen"), doesPathExist("./Data/x64/sound")]):
|
|
if not doesPathExist("./Data/x64/sound/" + "song_" + song["id"] + ".nus3bank"):
|
|
checkFile["GameFiles"]["MissingSound"] += 1
|
|
checkFile["GameFiles"]["MissingSoundList"].append(song["id"])
|
|
if not doesPathExist("./Data/x64/fumen/" + song["id"]):
|
|
checkFile["GameFiles"]["MissingFumen"] += 1
|
|
checkFile["GameFiles"]["MissingFumenList"].append(song["id"])
|
|
|
|
# Checking for vacant uniqueIds
|
|
for i in range(max(checkFile["stats"]["MaxId"], 1600)):
|
|
key = findKeyInList(list=songs, key="uniqueId", keyValue=i)
|
|
|
|
if key is not None:
|
|
# Updating GenreNoList of music_order.bin
|
|
if orders is not None:
|
|
for song in findAllObjects(
|
|
list=orders, key="uniqueId", keyValue=key["uniqueId"]
|
|
):
|
|
genre = {
|
|
"GenreNo": song["genreNo"],
|
|
"Name": Genres(song["genreNo"]).name,
|
|
"NumberofSongs": 0,
|
|
}
|
|
if (
|
|
findKeyInList(
|
|
list=checkFile["music_order.bin"]["GenreNoList"],
|
|
key="GenreNo",
|
|
keyValue=song["genreNo"],
|
|
)
|
|
is None
|
|
):
|
|
genre["NumberofSongs"] = len(
|
|
findAllObjects(
|
|
list=orders, key="genreNo", keyValue=song["genreNo"]
|
|
)
|
|
)
|
|
checkFile["music_order.bin"]["GenreNoList"].append(genre)
|
|
else:
|
|
# Finding unused Ids bellow 1599
|
|
if i < 1600:
|
|
checkFile["stats"]["UnusedUniqueIds"] += 1
|
|
checkFile["stats"]["UnusedUniqueIdsList"].append(i)
|
|
|
|
# Checking for doublons in wordlist
|
|
if words is not None:
|
|
for word in words:
|
|
if findDoubloninList(list=words, key="key", keyValue=word["key"]):
|
|
if word["key"] not in checkFile["wordlist.bin"]["DoublonsList"]:
|
|
checkFile["wordlist.bin"]["Doublons"] += 1
|
|
checkFile["wordlist.bin"]["DoublonsList"].append(word["key"])
|
|
|
|
|
|
# Sorting some values for better readability
|
|
if infos is not None:
|
|
checkFile["musicinfo.bin"]["GenreNoList"].sort(
|
|
key=lambda x: str(x["GenreNo"]), reverse=False
|
|
)
|
|
if orders is not None:
|
|
checkFile["music_order.bin"]["GenreNoList"].sort(
|
|
key=lambda x: str(x["GenreNo"]), reverse=False
|
|
)
|
|
|
|
# Writing everything to checks.json
|
|
json_object = json.dumps(checkFile, ensure_ascii=False, indent="\t")
|
|
# json_object = json.dumps(jsonList, ensure_ascii=False, indent="\t")
|
|
with open("./checks.json", "w", encoding="utf8") as outfile:
|
|
outfile.write(json_object)
|
|
print("Wrote checks.\n")
|