import argparse import ctypes import ujson as json import sys import struct def read_string(infile, length, encoding="cp932"): string_data = infile.read(length) try: return string_data.decode(encoding).strip("\0") except UnicodeDecodeError: # Cannot decode truncated string with half of a multibyte sequence appended (0x83) return string_data[:-1].decode(encoding).strip("\0") def write_string(outfile, input, length, fill="\0", encoding="cp932"): string_data = input[:length].encode(encoding) outfile.write(string_data) if len(input) < length: outfile.write("".join([fill] * (length - len(string_data))).encode(encoding)) def reader(data_ver, infile, song_count): song_entries = [] for i in range(song_count): title = read_string(infile, 0x40) title_ascii = read_string(infile, 0x40) genre = read_string(infile, 0x40) artist = read_string(infile, 0x40) ( texture_title, texture_artist, texture_genre, texture_load, texture_list, ) = struct.unpack("= 27: ( SPB_level, SPN_level, SPH_level, SPA_level, SPL_level, DPB_level, DPN_level, DPH_level, DPA_level, DPL_level, ) = struct.unpack("= 27: unk_sect1 = infile.read(0x286) else: unk_sect1 = infile.read(0xA0) song_id, volume = struct.unpack("= 27: ( SPB_ident, SPN_ident, SPH_ident, SPA_ident, SPL_ident, DPB_ident, DPN_ident, DPH_ident, DPA_ident, DPL_ident, ) = struct.unpack("= 22: afp_data = [] for x in range(10): afp_data.append(infile.read(0x20).hex()) else: afp_data = [] for x in range(9): afp_data.append(infile.read(0x20).hex()) if data_ver >= 26: unk_sect4 = infile.read(4) entries = { "song_id": song_id, "title": title, "title_ascii": title_ascii, "genre": genre, "artist": artist, "texture_title": texture_title, "texture_artist": texture_artist, "texture_genre": texture_genre, "texture_load": texture_load, "texture_list": texture_list, "font_idx": font_idx, "game_version": game_version, "other_folder": other_folder, "bemani_folder": bemani_folder, "splittable_diff": splittable_diff, "SPB_level": SPB_level, "SPN_level": SPN_level, "SPH_level": SPH_level, "SPA_level": SPA_level, "SPL_level": SPL_level, "DPB_level": DPB_level, "DPN_level": DPN_level, "DPH_level": DPH_level, "DPA_level": DPA_level, "DPL_level": DPL_level, "volume": volume, "SPB_ident": SPB_ident, "SPN_ident": SPN_ident, "SPH_ident": SPH_ident, "SPA_ident": SPA_ident, "SPL_ident": SPL_ident, "DPB_ident": DPB_ident, "DPN_ident": DPN_ident, "DPH_ident": DPH_ident, "DPA_ident": DPA_ident, "DPL_ident": DPL_ident, "bga_filename": bga_filename, "bga_delay": bga_delay, "afp_flag": afp_flag, "afp_data": afp_data, } # if data_ver == 80: # unk = { # 'unk_sect1': unk_sect1.hex(), # 'unk_sect2': unk_sect2.hex(), # 'unk_sect3': unk_sect3.hex(), # 'unk_sect4': unk_sect4.hex(), # } # elif data_ver < 80 and data_ver >= 27: # unk = { # 'unk_sect1': unk_sect1.hex(), # 'unk_sect4': unk_sect4.hex(), # } # elif data_ver == 26: # unk = { # 'unk_sect1': unk_sect1.hex(), # 'unk_sect2': unk_sect2.hex(), # 'unk_sect4': unk_sect4.hex(), # } # elif data_ver <= 25: # unk = { # 'unk_sect1': unk_sect1.hex(), # 'unk_sect2': unk_sect2.hex(), # } # # entries.update(unk) song_entries.append(entries) return song_entries def writer(data_ver, outfile, data): DATA_VERSION = data_ver MAX_ENTRIES = data_ver * 1000 + 1000 CUR_STYLE_ENTRIES = MAX_ENTRIES - 1000 # Write header outfile.write(b"IIDX") if data_ver == 80: outfile.write(struct.pack("= CUR_STYLE_ENTRIES: outfile.write(struct.pack("= 27: outfile.write( struct.pack( "= 27: outfile.write( bytes.fromhex( "00000000000001000000020000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000300000004000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ) ) else: outfile.write( bytes.fromhex( "00000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000" ) ) outfile.write(struct.pack("= 27: outfile.write( struct.pack( "= 22: for afp_data in song_data["afp_data"]: outfile.write(bytes.fromhex(afp_data)) if len(song_data["afp_data"]) == 9: outfile.write( bytes.fromhex( "0000000000000000000000000000000000000000000000000000000000000000" ) ) elif len(song_data["afp_data"]) == 10 and data_ver <= 21: for afp_data in song_data["afp_data"][:9]: outfile.write(bytes.fromhex(afp_data)) elif len(song_data["afp_data"]) == 9 and data_ver <= 21: for afp_data in song_data["afp_data"]: outfile.write(bytes.fromhex(afp_data)) if data_ver >= 26: outfile.write(bytes.fromhex("00000000")) def course_reader(infile, total_entries): course_entries = [] for i in range(total_entries): is_DP, course_num, stages = struct.unpack("