1
0
mirror of synced 2024-11-30 23:57:16 +01:00

utils.py: Merge checkValidHeader and validateHeaderMetadata

This commit is contained in:
Viv 2023-06-25 13:05:38 -04:00
parent 6d8bfb97d5
commit 903410dd99
2 changed files with 27 additions and 29 deletions

View File

@ -292,13 +292,9 @@ def readFumen(fumenFile, byteOrder=None, debug=False):
file = fumenFile file = fumenFile
size = os.fstat(file.fileno()).st_size size = os.fstat(file.fileno()).st_size
# Check for valid fumen header (first 432 bytes) using valid byte substrings # Check for valid fumen header (first 512 bytes) using valid byte substrings
fumenHeader = file.read(432) fumenHeader = file.read(512)
if not checkValidHeader(fumenHeader): checkValidHeader(fumenHeader)
debugPrint(f"Invalid header!")
# Read the next 80 bytes, which contains unknown information
fumenHeaderUnknown = file.read(80)
# validateHeaderMetadata(fumenHeaderUnknown)
# Determine: # Determine:
# - The byte order (big or little endian) # - The byte order (big or little endian)
@ -319,8 +315,8 @@ def readFumen(fumenFile, byteOrder=None, debug=False):
# Initialize the dict that will contain the chart information # Initialize the dict that will contain the chart information
song = {'measures': []} song = {'measures': []}
song['headerPadding'] = fumenHeader song['headerPadding'] = fumenHeader[:432]
song['headerMetadata'] = fumenHeaderUnknown song['headerMetadata'] = fumenHeader[-80:]
song['order'] = order song['order'] = order
song["length"] = totalMeasures song["length"] = totalMeasures

View File

@ -5,28 +5,30 @@ import math
from tja2fumen.constants import simpleHeaders, byte_strings from tja2fumen.constants import simpleHeaders, byte_strings
def checkValidHeader(header): def checkValidHeader(headerBytes):
# These simple headers (substrings repeated 36 times) are used for many Gen2 systems (AC, Wii, etc.) # Fumen headers should contain 512 bytes.
if header in simpleHeaders: assert len(headerBytes) == 512
return True # The header for fumens can be split into two groups: The first 432 bytes, and the last 80 bytes.
# Starting with Gen3, they began using unique headers for every song. (3DS and PSPDX are the big offenders.) headerPadding = headerBytes[:432]
# They seem to be some random combination of b_x00 + one of the non-null byte substrings. headerMetadata = headerBytes[-80:]
# To avoid enumerating every combination of 432 bytes, we do a lazy check instead.
elif (byte_strings['x00'] in header and # 1. Check the header's padding bytes for several possible combinations
any(b in header for b in [byte_strings[key] for key in ['431', '432', '433', '434', 'V1', 'V2', 'V3']])): # 1a. These simple headers (substrings repeated 36 times) are used for many Gen2 systems (AC, Wii, etc.)
return True cond1 = headerPadding in simpleHeaders
# The PS4 song 'wii5op' is a special case: It throws in this odd 'g1' string in combo with other substrings. # 1b. Starting with Gen3, they began using unique headers for every song. (3DS and PSPDX are the big offenders.)
elif (byte_strings['g1'] in header and # - They seem to be some random combination of b_x00 + one of the non-null byte substrings.
any(b in header for b in [byte_strings[key] for key in ['431', 'V2']])): # - To avoid enumerating every combination of 432 bytes, we do a lazy check instead.
return True cond2 = (byte_strings['x00'] in headerPadding and
any(b in headerPadding for b in
[byte_strings[key] for key in ['431', '432', '433', '434', 'V1', 'V2', 'V3']]))
# 1c. The PS4 song 'wii5op' is a special case: It throws in this odd 'g1' string in combo with 2 other substrings.
cond3 = (byte_strings['g1'] in headerPadding and
any(b in headerPadding for b in [byte_strings[key] for key in ['431', 'V2']]))
# Otherwise, this is some unknown header we haven't seen before. # Otherwise, this is some unknown header we haven't seen before.
# Typically, these will be tja2bin.exe converted files with a completely invalid header. assert cond1 or cond2 or cond3, "Header padding bytes do not match expected fumen byte substrings."
else:
return False
# 2. Check the header's metadata bytes
def validateHeaderMetadata(headerBytes): for idx, val in enumerate(headerMetadata):
for idx, val in enumerate(headerBytes):
# 0. Unknown # 0. Unknown
# Notes: # Notes:
# * Breakdown of distribution of different byte combinations: # * Breakdown of distribution of different byte combinations: