Bug fixes

This commit is contained in:
Cainan 2024-06-28 17:31:50 +01:00
parent 10fdaa492d
commit 6c72cf631b

View File

@ -4,6 +4,7 @@ import glob
import concurrent.futures import concurrent.futures
import gzip import gzip
import json import json
import numpy as np
import os import os
import random import random
import re import re
@ -366,7 +367,7 @@ def update_selection_count(event=None):
if platform == "PS4": if platform == "PS4":
max_entries = 400 max_entries = 400
elif platform == "WIIU3": elif platform == "WIIU3":
max_entries = 199 max_entries = 90 # this is due to us using RGBA for textures. High quality = less textures can be added.
elif platform == "NS1": elif platform == "NS1":
max_entries = 600 max_entries = 600
elif platform == "PTB": elif platform == "PTB":
@ -1491,10 +1492,6 @@ def generate_wiiu3_texture(id, genreNo, current_unique_id, append_ura, custom_so
rotated_font_path = 'data/_resource/font/KozGoPr6NRegular.otf' rotated_font_path = 'data/_resource/font/KozGoPr6NRegular.otf'
create_images(data, id, genreNo, font_path, rotated_font_path, current_unique_id, append_ura) create_images(data, id, genreNo, font_path, rotated_font_path, current_unique_id, append_ura)
import os
from PIL import Image
import struct
class TextureSurface: class TextureSurface:
def __init__(self): def __init__(self):
self.mipmaps = [] self.mipmaps = []
@ -1517,6 +1514,8 @@ class NutTexture:
def getNutFormat(self): def getNutFormat(self):
if self.pixelInternalFormat == 'RGBA': if self.pixelInternalFormat == 'RGBA':
return 14 return 14
elif self.pixelInternalFormat == 'CompressedRgbaS3tcDxt5Ext':
return 28 # Example format code for DXT5, adjust as necessary
raise NotImplementedError("Only RGBA format is implemented") raise NotImplementedError("Only RGBA format is implemented")
class NUT: class NUT:
@ -1605,6 +1604,77 @@ class NUT:
with open(output_path, 'wb') as f: with open(output_path, 'wb') as f:
f.write(data) f.write(data)
def modify_nut_file_dds(self, file_path, output_path):
# Set replacement bytes to 00
with open(file_path, 'rb') as f:
data = bytearray(f.read())
del data[0x0000:0x0280]
# Given byte string
byte_string = "4E 54 50 33 02 00 00 06 00 00 00 00 00 00 00 00 00 00 F0 40 00 00 00 00 00 00 EF D0 00 70 00 00 00 05 00 02 02 D0 00 40 00 00 00 00 00 00 00 00 00 00 02 80 00 00 00 00 00 00 00 00 00 00 00 00 00 00 B4 00 00 00 2D 00 00 00 0B 40 00 00 02 D0 00 00 00 C0 00 00 00 00 00 00 00 00 00 00 00 00 65 58 74 00 00 00 00 20 00 00 00 10 00 00 00 00 47 49 44 58 00 00 00 10 00 00 00 00 00 00 00 00 00 01 86 10 00 00 00 00 00 01 85 A0 00 70 00 00 00 05 00 02 02 D0 00 68 00 00 00 00 00 00 00 00 00 00 F1 E0 00 00 00 00 00 00 00 00 00 00 00 00 00 01 24 80 00 00 49 20 00 00 12 50 00 00 04 A0 00 00 01 10 00 00 00 00 00 00 00 00 00 00 00 00 65 58 74 00 00 00 00 20 00 00 00 10 00 00 00 00 47 49 44 58 00 00 00 10 00 00 00 01 00 00 00 00 00 00 F0 40 00 00 00 00 00 00 EF D0 00 70 00 00 00 05 00 02 02 D0 00 40 00 00 00 00 00 00 00 00 00 02 77 10 00 00 00 00 00 00 00 00 00 00 00 00 00 00 B4 00 00 00 2D 00 00 00 0B 40 00 00 02 D0 00 00 00 C0 00 00 00 00 00 00 00 00 00 00 00 00 65 58 74 00 00 00 00 20 00 00 00 10 00 00 00 00 47 49 44 58 00 00 00 10 00 00 00 02 00 00 00 00 00 00 C8 50 00 00 00 00 00 00 C7 E0 00 70 00 00 00 05 00 02 00 60 01 90 00 00 00 00 00 00 00 00 00 03 66 70 00 00 00 00 00 00 00 00 00 00 00 00 00 00 96 00 00 00 25 80 00 00 09 60 00 00 02 60 00 00 00 A0 00 00 00 00 00 00 00 00 00 00 00 00 65 58 74 00 00 00 00 20 00 00 00 10 00 00 00 00 47 49 44 58 00 00 00 10 00 00 00 04 00 00 00 00 00 00 74 A0 00 00 00 00 00 00 74 40 00 60 00 00 00 04 00 02 00 38 01 90 00 00 00 00 00 00 00 00 00 04 2D E0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 57 80 00 00 15 E0 00 00 05 80 00 00 01 60 65 58 74 00 00 00 00 20 00 00 00 10 00 00 00 00 47 49 44 58 00 00 00 10 00 00 00 04 00 00 00 00 00 00 74 A0 00 00 00 00 00 00 74 40 00 60 00 00 00 04 00 02 00 38 01 90 00 00 00 00 00 00 00 00 00 04 A1 C0 00 00 00 00 00 00 00 00 00 00 00 00 00 00 57 80 00 00 15 E0 00 00 05 80 00 00 01 60 65 58 74 00 00 00 00 20 00 00 00 10 00 00 00 00 47 49 44 58 00 00 00 10 00 00 00 05 00 00 00 00"
# Convert the byte string into bytes
bytes_data = bytes.fromhex(byte_string.replace(' ', ''))
# Concatenate the bytes
data = bytes_data + data
with open(output_path, 'wb') as f:
f.write(data)
def convert_png_to_dds(png_file, dds_file):
# Ensure the input PNG file exists
if not os.path.isfile(png_file):
print(f"Error: {png_file} does not exist.")
return False
# Construct the command to convert using nvcompress
command = [
'nvcompress', # Assuming nvcompress is in your PATH
'-silent', # Optional: Suppress output from nvcompress
'-bc3', # DXT5 compression (BC3 in nvcompress)
'-alpha', # Alpha Channel
'-highest', # Alpha Channel
png_file, # Input PNG file
dds_file # Output DDS file
]
# Run the command using subprocess
try:
subprocess.run(command, check=True)
print(f"Conversion successful: {png_file} -> {dds_file}")
return True
except subprocess.CalledProcessError as e:
print(f"Error during conversion: {e}")
return False
def convert_png_files_in_folder(input_folder, output_folder):
# Ensure the input folder exists
if not os.path.isdir(input_folder):
print(f"Error: {input_folder} is not a valid directory.")
return
# Create the output folder if it doesn't exist
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# Iterate through files in the input folder
for filename in os.listdir(input_folder):
if filename.endswith(".png"):
input_path = os.path.join(input_folder, filename)
output_filename = os.path.splitext(filename)[0] + ".dds"
output_path = os.path.join(output_folder, output_filename)
# Convert PNG to DDS
success = convert_png_to_dds(input_path, output_path)
if success:
print(f"Conversion successful: {input_path} -> {output_path}")
else:
print(f"Conversion failed: {input_path}")
def load_png_to_texture(filepath): def load_png_to_texture(filepath):
with Image.open(filepath) as img: with Image.open(filepath) as img:
img = img.convert("RGBA") img = img.convert("RGBA")
@ -1614,6 +1684,42 @@ def load_png_to_texture(filepath):
texture.add_mipmap(mipmap_data) texture.add_mipmap(mipmap_data)
return texture return texture
def read_dds_to_bytes(dds_file):
try:
with open(dds_file, "rb") as f:
dds_bytes = f.read()
return dds_bytes
except FileNotFoundError:
print(f"Error: File '{dds_file}' not found.")
return None
except Exception as e:
print(f"Error reading DDS file '{dds_file}': {e}")
return None
def load_dds_to_texture(filepath):
with Image.open(filepath) as img:
#img = img.convert("RGBA")
width, height = img.size
mipmap_data = read_dds_to_bytes(filepath)
texture = NutTexture(width, height, "CompressedRgbaS3tcDxt5Ext", "CompressedRgbaS3tcDxt5Ext")
#texture.add_mipmap(mipmap_data)
return texture
def generate_nut_texture_dds(input_folder, output_file):
nut = NUT()
convert_png_files_in_folder(input_folder, input_folder)
for filename in os.listdir(input_folder):
if filename.endswith(".dds"):
texture = load_dds_to_texture(os.path.join(input_folder, filename))
nut.add_texture(texture)
# Save the NUT file
nut.save(output_file)
# Modify the saved NUT file
#nut.modify_nut_file(output_file, output_file)
nut.modify_nut_file_dds(output_file, output_file)
def generate_nut_texture(input_folder, output_file): def generate_nut_texture(input_folder, output_file):
nut = NUT() nut = NUT()
for filename in os.listdir(input_folder): for filename in os.listdir(input_folder):
@ -1627,7 +1733,6 @@ def generate_nut_texture(input_folder, output_file):
# Modify the saved NUT file # Modify the saved NUT file
nut.modify_nut_file(output_file, output_file) nut.modify_nut_file(output_file, output_file)
# file encryption # file encryption
def encrypt_file_ptb(input_file, output_file): def encrypt_file_ptb(input_file, output_file):
# Generate a random initialization vector (IV) # Generate a random initialization vector (IV)
@ -2349,9 +2454,6 @@ def remove_musicinfo_leftover(directory_path):
except Exception as e: except Exception as e:
print(f"Error deleting {directory_path}: {e}") print(f"Error deleting {directory_path}: {e}")
import os
import shutil
import glob
def remove_texture_leftover(texture_output_dir): def remove_texture_leftover(texture_output_dir):
try: try:
@ -2442,44 +2544,6 @@ def export_data():
audio_output_dir = f"out/content/{formatted_id}/sound" audio_output_dir = f"out/content/{formatted_id}/sound"
texture_output_dir = f"out/content/{formatted_id}/texture" texture_output_dir = f"out/content/{formatted_id}/texture"
try:
if len(selected_items) > max_entries:
messagebox.showerror("Selection Limit Exceeded", f"Maximum {max_entries} entries can be selected for {game_platform}.")
return
# Load preview position data
with open(previewpos_path, "r", encoding="utf-8") as previewpos_file:
previewpos_data = json.load(previewpos_file)
if custom_songs:
with open(custom_previewpos_path, "r", encoding="utf-8") as custom_previewpos_file:
custom_previewpos_data = json.load(custom_previewpos_file)
# Copy fumen folders for selected songs to output directory
for item_id in selected_items:
song_id = tree.item(item_id)["values"][1]
fumen_folder_path = os.path.join(data_dir, "fumen", str(song_id))
if os.path.exists(fumen_folder_path):
if game_platform == "WIIU3":
#shutil.copytree(fumen_folder_path, os.path.join(fumen_output_dir, f"{song_id}"))
print()
else:
shutil.copytree(fumen_folder_path, os.path.join(fumen_output_dir, f"{song_id}"))
song_info = next((item for item in music_info["items"] if item["id"] == song_id), None)
if custom_songs:
for item_id in selected_items:
song_id = tree.item(item_id)["values"][1]
custom_fumen_folder_path = os.path.join(custom_data_dir, "fumen", str(song_id))
if os.path.exists(fumen_folder_path):
if game_platform == "WIIU3":
#shutil.copytree(fumen_folder_path, os.path(fumen_output_dir, f"{song_id}"))
print(" ")
else:
shutil.copytree(fumen_folder_path, os.path.join(fumen_output_dir, f"{song_id}"))
song_info = next((item for item in custom_music_info["items"] if item["id"] == song_id), None)
def copy_fumens_ura(): def copy_fumens_ura():
# Copy fumen folders for selected songs to output directory # Copy fumen folders for selected songs to output directory
song_id = tree.item(item_id)["values"][1] song_id = tree.item(item_id)["values"][1]
@ -2535,6 +2599,42 @@ def export_data():
else: else:
shutil.copytree(fumen_folder_path, os.path.join(fumen_output_dir, f"{song_id}")) shutil.copytree(fumen_folder_path, os.path.join(fumen_output_dir, f"{song_id}"))
try:
if len(selected_items) > max_entries:
messagebox.showerror("Selection Limit Exceeded", f"Maximum {max_entries} entries can be selected for {game_platform}.")
return
# Load preview position data
with open(previewpos_path, "r", encoding="utf-8") as previewpos_file:
previewpos_data = json.load(previewpos_file)
if custom_songs:
with open(custom_previewpos_path, "r", encoding="utf-8") as custom_previewpos_file:
custom_previewpos_data = json.load(custom_previewpos_file)
# Copy fumen folders for selected songs to output directory
if game_platform == "WIIU3":
print()
else:
for item_id in selected_items:
song_id = tree.item(item_id)["values"][1]
fumen_folder_path = os.path.join(data_dir, "fumen", str(song_id))
if os.path.exists(fumen_folder_path):
shutil.copytree(fumen_folder_path, os.path.join(fumen_output_dir, f"{song_id}"))
song_info = next((item for item in music_info["items"] if item["id"] == song_id), None)
if custom_songs:
for item_id in selected_items:
song_id = tree.item(item_id)["values"][1]
custom_fumen_folder_path = os.path.join(custom_data_dir, "fumen", str(song_id))
if os.path.exists(custom_fumen_folder_path):
shutil.copytree(custom_fumen_folder_path, os.path.join(fumen_output_dir, f"{song_id}"))
song_info = next((item for item in custom_music_info["items"] if item["id"] == song_id), None)
for item_id in selected_items: for item_id in selected_items:
song_id = tree.item(item_id)["values"][1] song_id = tree.item(item_id)["values"][1]
if custom_songs: if custom_songs:
@ -2548,9 +2648,12 @@ def export_data():
# Calculate song_order based on genreNo and current_unique_id # Calculate song_order based on genreNo and current_unique_id
song_order = (int(song_info["genreNo"]) * 1000) + current_unique_id song_order = (int(song_info["genreNo"]) * 1000) + current_unique_id
if game_platform == "WIIU3": if game_platform == "WIIU3":
if song_info["id"].startswith("cs"): pattern = r"^cs\d{4}$"
if re.match(pattern, song_info["id"]):
custom_songs == True custom_songs == True
else: else:
custom_songs == False custom_songs == False
@ -2622,7 +2725,7 @@ def export_data():
root.append(wiiu3_song_info_xml) root.append(wiiu3_song_info_xml)
if song_info["id"].startswith("cs"): if re.match(pattern, song_info["id"]):
custom_songs == True custom_songs == True
generate_wiiu3_texture(song_info["id"], song_info["genreNo"], current_unique_id, append_ura=False, custom_songs=True) generate_wiiu3_texture(song_info["id"], song_info["genreNo"], current_unique_id, append_ura=False, custom_songs=True)
else: else:
@ -2633,7 +2736,7 @@ def export_data():
root.set('num', str(db_data_count)) root.set('num', str(db_data_count))
save_xml_to_file(root, file_path) save_xml_to_file(root, file_path)
if song_info["id"].startswith("cs"): if re.match(pattern, song_info["id"]):
custom_songs == True custom_songs == True
copy_fumens_custom() copy_fumens_custom()
else: else:
@ -2651,7 +2754,7 @@ def export_data():
output_file = os.path.join(texture_output_dir, f"{song_info['id']}.nut") output_file = os.path.join(texture_output_dir, f"{song_info['id']}.nut")
generate_nut_texture(input_folder, output_file) generate_nut_texture(input_folder, output_file)
if song_info["id"].startswith("cs"): if re.match(pattern, song_info["id"]):
custom_songs == True custom_songs == True
convert_song_wiiu(song_id, custom_songs=True) convert_song_wiiu(song_id, custom_songs=True)
else: else:
@ -2683,7 +2786,7 @@ def export_data():
wiiu3_song_info_xml = create_wiiu3_song_info_ura_xml(song_info, current_unique_id, song_order, word_list) wiiu3_song_info_xml = create_wiiu3_song_info_ura_xml(song_info, current_unique_id, song_order, word_list)
root.append(wiiu3_song_info_xml) root.append(wiiu3_song_info_xml)
if song_info["id"].startswith("cs"): if re.match(pattern, song_info["id"]):
custom_songs == True custom_songs == True
generate_wiiu3_texture(song_info["id"], song_info["genreNo"], current_unique_id, append_ura=True, custom_songs=True) generate_wiiu3_texture(song_info["id"], song_info["genreNo"], current_unique_id, append_ura=True, custom_songs=True)
else: else:
@ -2706,7 +2809,7 @@ def export_data():
output_file = os.path.join(texture_output_dir, f"ex_{song_info['id']}.nut") output_file = os.path.join(texture_output_dir, f"ex_{song_info['id']}.nut")
generate_nut_texture(input_folder, output_file) generate_nut_texture(input_folder, output_file)
if song_info["id"].startswith("cs"): if re.match(pattern, song_info["id"]):
custom_songs == True custom_songs == True
convert_song_wiiu(song_id, custom_songs=True) convert_song_wiiu(song_id, custom_songs=True)
else: else:
@ -2719,7 +2822,7 @@ def export_data():
remove_musicinfo_leftover(output_dir) remove_musicinfo_leftover(output_dir)
remove_texture_leftover(texture_output_dir) remove_texture_leftover(texture_output_dir)
if song_info["id"].startswith("cs"): if re.match(pattern, song_info["id"]):
custom_songs == True custom_songs == True
else: else:
custom_songs == False custom_songs == False