Attempt to handle remaining header bytes
This commit is contained in:
parent
62e4be1b81
commit
1f3bf163b9
@ -69,11 +69,13 @@ byte_strings = {
|
|||||||
|
|
||||||
simpleHeaders = [b * 36 for b in [byte_strings['431'], byte_strings['V1'], byte_strings['V2']]]
|
simpleHeaders = [b * 36 for b in [byte_strings['431'], byte_strings['V1'], byte_strings['V2']]]
|
||||||
|
|
||||||
# This sample header for the "unknown header bytes" is built from the investigations in utils/validateHeaderMetadata
|
# Create a sample header pre-filled with known bytes
|
||||||
# However, it's missing song-specific metadata from bytes 12, 16, 20, and (perhaps optionally), 76, 77 and 78.
|
|
||||||
unknownHeaderSample = [0] * 80
|
unknownHeaderSample = [0] * 80
|
||||||
|
# The following bytes are hardcoded by tja2fumen.exe (implying they have little/no effect on how the song is parsed)
|
||||||
unknownHeaderSample[4] = 16
|
unknownHeaderSample[4] = 16
|
||||||
unknownHeaderSample[5] = 39
|
unknownHeaderSample[5] = 39
|
||||||
|
unknownHeaderSample[12] = 10
|
||||||
|
unknownHeaderSample[16] = 8
|
||||||
unknownHeaderSample[21] = 255
|
unknownHeaderSample[21] = 255
|
||||||
unknownHeaderSample[22] = 255
|
unknownHeaderSample[22] = 255
|
||||||
unknownHeaderSample[23] = 255
|
unknownHeaderSample[23] = 255
|
||||||
@ -89,3 +91,15 @@ unknownHeaderSample[60] = 1
|
|||||||
unknownHeaderSample[64] = 30
|
unknownHeaderSample[64] = 30
|
||||||
unknownHeaderSample[68] = 30
|
unknownHeaderSample[68] = 30
|
||||||
unknownHeaderSample[72] = 20
|
unknownHeaderSample[72] = 20
|
||||||
|
unknownHeaderSample[76] = 78
|
||||||
|
unknownHeaderSample[77] = 97
|
||||||
|
unknownHeaderSample[78] = 188
|
||||||
|
|
||||||
|
DIFFICULTY_BYTES = {
|
||||||
|
'Easy': [112, 23],
|
||||||
|
'Normal': [88, 27],
|
||||||
|
'Hard': [88, 27],
|
||||||
|
'Oni': [64, 31],
|
||||||
|
'Ura': [64, 31],
|
||||||
|
'Edit': [64, 31]
|
||||||
|
}
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
from copy import deepcopy
|
from copy import deepcopy
|
||||||
|
|
||||||
from constants import TJA_NOTE_TYPES, unknownHeaderSample
|
from utils import computeSoulGaugeByte
|
||||||
|
from constants import TJA_NOTE_TYPES, DIFFICULTY_BYTES, unknownHeaderSample
|
||||||
|
|
||||||
# Filler metadata that the `writeFumen` function expects
|
# Filler metadata that the `writeFumen` function expects
|
||||||
default_note = {'type': '', 'pos': 0.0, 'item': 0, 'padding': 0.0,
|
default_note = {'type': '', 'pos': 0.0, 'item': 0, 'padding': 0.0,
|
||||||
@ -101,6 +102,7 @@ def convertTJAToFumen(fumen, tja):
|
|||||||
currentBranch = 'normal' # TODO: Program in branch support
|
currentBranch = 'normal' # TODO: Program in branch support
|
||||||
tja['measures'] = preprocessTJAMeasures(tja)
|
tja['measures'] = preprocessTJAMeasures(tja)
|
||||||
currentDrumroll = None
|
currentDrumroll = None
|
||||||
|
total_notes = 0
|
||||||
|
|
||||||
# Parse TJA measures to create converted TJA -> Fumen file
|
# Parse TJA measures to create converted TJA -> Fumen file
|
||||||
tjaConverted = {'measures': []}
|
tjaConverted = {'measures': []}
|
||||||
@ -172,9 +174,11 @@ def convertTJAToFumen(fumen, tja):
|
|||||||
note['hits'] = tja['metadata']['balloon'].pop(0)
|
note['hits'] = tja['metadata']['balloon'].pop(0)
|
||||||
note['hitsPadding'] = 0
|
note['hitsPadding'] = 0
|
||||||
currentDrumroll = note
|
currentDrumroll = note
|
||||||
|
total_notes -= 1
|
||||||
if note['type'] in ["Drumroll", "DRUMROLL"]:
|
if note['type'] in ["Drumroll", "DRUMROLL"]:
|
||||||
note['drumrollBytes'] = b'\x00\x00\x00\x00\x00\x00\x00\x00'
|
note['drumrollBytes'] = b'\x00\x00\x00\x00\x00\x00\x00\x00'
|
||||||
currentDrumroll = note
|
currentDrumroll = note
|
||||||
|
total_notes -= 1
|
||||||
measureFumen[currentBranch][note_counter] = note
|
measureFumen[currentBranch][note_counter] = note
|
||||||
note_counter += 1
|
note_counter += 1
|
||||||
measureFumen[currentBranch]['length'] = note_counter
|
measureFumen[currentBranch]['length'] = note_counter
|
||||||
@ -192,7 +196,14 @@ def convertTJAToFumen(fumen, tja):
|
|||||||
else:
|
else:
|
||||||
currentDrumroll['duration'] += measureDurationBase
|
currentDrumroll['duration'] += measureDurationBase
|
||||||
|
|
||||||
tjaConverted['headerUnknown'] = b"".join(i.to_bytes(1, 'little') for i in unknownHeaderSample)
|
total_notes += note_counter
|
||||||
|
|
||||||
|
# Take a stock header metadata sample and add song-specific metadata
|
||||||
|
headerMetadata = unknownHeaderSample
|
||||||
|
headerMetadata[8] = DIFFICULTY_BYTES[tja['metadata']['course']][0]
|
||||||
|
headerMetadata[9] = DIFFICULTY_BYTES[tja['metadata']['course']][1]
|
||||||
|
headerMetadata[20] = computeSoulGaugeByte(total_notes)
|
||||||
|
tjaConverted['headerUnknown'] = b"".join(i.to_bytes(1, 'little') for i in headerMetadata)
|
||||||
tjaConverted['order'] = '<'
|
tjaConverted['order'] = '<'
|
||||||
tjaConverted['length'] = len(tjaConverted['measures'])
|
tjaConverted['length'] = len(tjaConverted['measures'])
|
||||||
tjaConverted['unknownMetadata'] = 0
|
tjaConverted['unknownMetadata'] = 0
|
||||||
|
@ -1,5 +1,6 @@
|
|||||||
import sys
|
import sys
|
||||||
import struct
|
import struct
|
||||||
|
import math
|
||||||
|
|
||||||
from constants import simpleHeaders, byte_strings
|
from constants import simpleHeaders, byte_strings
|
||||||
|
|
||||||
@ -190,6 +191,13 @@ def validateHeaderMetadata(headerBytes):
|
|||||||
assert val == 0, f"Expected 0 at position '{idx}', got '{val}' instead."
|
assert val == 0, f"Expected 0 at position '{idx}', got '{val}' instead."
|
||||||
|
|
||||||
|
|
||||||
|
def computeSoulGaugeByte(n_notes):
|
||||||
|
# I don't think this is fully accurate. It doesn't work for non-Oni songs, and it's usually off by a bit.
|
||||||
|
A = -85.548628
|
||||||
|
B = 44.780199
|
||||||
|
return round(A+B*math.log(n_notes))
|
||||||
|
|
||||||
|
|
||||||
def readStruct(file, order, format_string, seek=None):
|
def readStruct(file, order, format_string, seek=None):
|
||||||
"""
|
"""
|
||||||
Interpret bytes as packed binary data.
|
Interpret bytes as packed binary data.
|
||||||
|
Loading…
x
Reference in New Issue
Block a user