simfile-scripts/change_sync_bias.py
2022-07-28 21:17:16 -07:00

86 lines
2.7 KiB
Python

import argparse
from decimal import Decimal
import sys
from typing import Union
import simfile
from simfile.dir import SimfilePack
class ChangeSyncBiasArgs:
"""Stores the command-line arguments for this script."""
pack: str
itg_to_null: bool
null_to_itg: bool
def argparser():
"""Get an ArgumentParser instance for this command-line script."""
parser = argparse.ArgumentParser(prefix_chars="-+")
parser.add_argument("pack", type=str, help="path to the pack to modify")
group = parser.add_mutually_exclusive_group(required=True)
group.add_argument(
"-9", "--itg-to-null", action="store_true", help="subtract 9ms from offsets"
)
group.add_argument(
"+9", "--null-to-itg", action="store_true", help="add 9ms to offsets"
)
return parser
def adjust_offset(
obj: Union[simfile.types.Simfile, simfile.ssc.SSCChart],
delta: Decimal,
):
"""Add the delta to the simfile or SSC chart's offset, if present."""
if obj.offset is not None:
obj.offset = str(Decimal(obj.offset) + delta)
def change_sync_bias(simfile_path: str, args: ChangeSyncBiasArgs):
"""
Add or subtract 9 milliseconds to the simfile's offset,
as well as any SSC charts with their own timing data.
This saves the updated simfile to its original location
and writes a backup copy with a ~ appended to the filename.
"""
# Map the +9 or -9 arg to the actual offset delta.
#
# We don't have to check both itg_to_null and null_to_itg
# because the mutually exclusive & required argument group
# ensures that exactly one of them will be True.
delta = Decimal("-0.009" if args.itg_to_null else "+0.009")
# You could specify output_filename here to write the updated file elsewhere
with simfile.mutate(
input_filename=f"{simfile_path}",
backup_filename=f"{simfile_path}~",
) as sf:
# Always adjust the simfile's offset
adjust_offset(sf, delta)
# Additionally try to adjust SSC charts' offsets.
# This won't do anything unless the chart has its own timing data.
if isinstance(sf, simfile.ssc.SSCSimfile):
for chart in sf.charts:
adjust_offset(chart, delta)
def main(argv):
# Parse command-line arguments
args = argparser().parse_args(argv[1:], namespace=ChangeSyncBiasArgs())
# Iterate over SimfileDirectory objects from the pack
# so that we can easily get the .sm and/or .ssc paths
for simfile_dir in SimfilePack(args.pack).simfile_dirs():
# Try to update whichever formats exist
for simfile_path in [simfile_dir.sm_path, simfile_dir.ssc_path]:
if simfile_path:
change_sync_bias(simfile_path, args)
if __name__ == "__main__":
main(sys.argv)