437 lines
15 KiB
Python
Executable File
437 lines
15 KiB
Python
Executable File
import datetime
|
|
import hashlib
|
|
import os
|
|
import re
|
|
import sys
|
|
|
|
from audio_logger import Logger, LogSeverity
|
|
from p4_helper import P4Helper
|
|
|
|
DEFAULT_BRANCH = 'dev_ng'
|
|
|
|
# Runtime data
|
|
NOW_START = datetime.datetime.now()
|
|
NOW_START_STR = NOW_START.strftime('%y_%m_%d__%H_%M_%S')
|
|
|
|
RPF_ROOT_PATH = r'x:\gta5\audio\{branch}\STAGINGRPF'
|
|
|
|
LOG_DIR = os.path.join(r'C:\Temp\Logs\Audio RPFs', NOW_START_STR)
|
|
LOG_FILENAME = r'run_log_%s.txt'
|
|
|
|
PLATFORMS = (
|
|
'PS4',
|
|
'XBOXONE',
|
|
'PC',
|
|
'XBOXSERIES',
|
|
'PS5'
|
|
)
|
|
|
|
# Now that we have the data for the disk build, we no longer need
|
|
# to rebuild the RPFs for next-gen consoles, only audio.rpf and
|
|
# audio_rel.rpf need to be built for these
|
|
EXCLUDED_RPF_BUILD_PLATFORMS = (
|
|
'PS4',
|
|
'XBOXONE',
|
|
'PC'
|
|
)
|
|
|
|
DEV_IGNORE_PACKS_LIST = (
|
|
#'^PS_(.*)',
|
|
'(.*)DLC(.*)',
|
|
)
|
|
|
|
RELEASE_IGNORE_PACKS_LIST = {
|
|
'PS4' : (
|
|
'(.*)DLC(.*)',
|
|
'TEST(.*)',
|
|
'^CUTSCENE$',
|
|
'^CUTSCENE_MASTERED_TRIMMED$',
|
|
),
|
|
'XBOXONE' : (
|
|
'^PS_(.*)',
|
|
'(.*)DLC(.*)',
|
|
'TEST(.*)',
|
|
'^CUTSCENE$',
|
|
'^CUTSCENE_MASTERED_TRIMMED$',
|
|
),
|
|
'PC' : (
|
|
'(.*)DLC(.*)',
|
|
'TEST(.*)',
|
|
'^CUTSCENE$',
|
|
'^CUTSCENE_MASTERED_TRIMMED$',
|
|
),
|
|
'PS5' : (
|
|
'(.*)DLC(.*)',
|
|
'TEST(.*)',
|
|
'^CUTSCENE$',
|
|
'^CUTSCENE_MASTERED_TRIMMED$',
|
|
),
|
|
'XBOXSERIES' : (
|
|
'(.*)DLC(.*)',
|
|
'TEST(.*)',
|
|
'^CUTSCENE$',
|
|
'^CUTSCENE_MASTERED_TRIMMED$',
|
|
),
|
|
}
|
|
|
|
IGNORE_EXCEPTION_PACKS_LIST = (
|
|
'DLC_GTAO$',
|
|
'DLCTU$',
|
|
)
|
|
|
|
|
|
# Runtime args
|
|
audio_path = None
|
|
rage_builder_path = None
|
|
package_path_release = None
|
|
package_path_main = None
|
|
tools_root_path = None
|
|
|
|
packlist_path_main = None
|
|
packlist_path_release = None
|
|
input_path = None
|
|
audio_output_path = None
|
|
sfx_output_path = None
|
|
build_pack_path = None
|
|
working_path = None
|
|
rpf_source_path = None
|
|
|
|
logger = None
|
|
p4 = None
|
|
|
|
def generate_audio_rpfs(platform, rebuild, branch):
|
|
global logger
|
|
global p4
|
|
|
|
logger = Logger('Audio RPFs', LOG_DIR, LOG_FILENAME % platform)
|
|
|
|
if platform in EXCLUDED_RPF_BUILD_PLATFORMS:
|
|
logger.log("%s is set to be excluded from RPF builds" %platform, LogSeverity.INFO)
|
|
return 0
|
|
|
|
# Initialise paths to required dirs and files
|
|
if not init_paths(platform, branch):
|
|
logger.log("Failed to initialise paths", LogSeverity.ERROR)
|
|
failed()
|
|
return -1
|
|
|
|
# connect to p4
|
|
p4 = P4Helper(logger)
|
|
p4.connect()
|
|
cl_number = p4.create_cl("Daily Sync [GTA5] " + branch + " : Audio RPF Build - " + platform)
|
|
|
|
if cl_number == -1:
|
|
failed()
|
|
return -1
|
|
|
|
# build sfx rpfs
|
|
if not generate_rpfs(rebuild, platform, cl_number):
|
|
failed()
|
|
return -1
|
|
|
|
#we dont need to build audio.rpf and audio_rel.rpf anymore for V
|
|
#re-enabling audio(_rel).rpf building for gen9 platforms
|
|
if(platform.upper() != 'PS5' and platform.upper() != 'XBOXSERIES'):
|
|
return 0
|
|
|
|
# Generate dev audio RPF file
|
|
if not generate_audio_rpf(platform, cl_number):
|
|
failed()
|
|
return -1
|
|
|
|
# Generate release audio RPF file
|
|
if not generate_audio_rpf(platform, cl_number, True):
|
|
failed()
|
|
return -1
|
|
|
|
if not p4.submit_cl(cl_number):
|
|
p4.revert_cl(cl_number, ".rpf", True)
|
|
return -1
|
|
|
|
logger.save()
|
|
return 0
|
|
|
|
|
|
def init_paths(platform, branch):
|
|
global build_path
|
|
global audio_path
|
|
global rage_builder_path
|
|
global package_path_release
|
|
global package_path_main
|
|
global package_path_release_durango
|
|
global package_path_main_durango
|
|
global package_path_release_orbis
|
|
global package_path_main_orbis
|
|
global package_path_release_win64
|
|
global package_path_main_win64
|
|
|
|
global tools_root_path
|
|
|
|
global packlist_path_main
|
|
global packlist_path_release
|
|
global package_path_release
|
|
global input_path
|
|
global audio_output_path
|
|
global sfx_output_path
|
|
global build_pack_path
|
|
global rpf_source_path
|
|
global output_platform_name
|
|
|
|
#ragebuilder forces win32 if 'PC' is in output path so we will make sure to output to 'x64'
|
|
output_platform_name = platform
|
|
if platform.upper() == 'PC':
|
|
output_platform_name = 'X64'
|
|
|
|
# Init tools root path
|
|
tools_root_path = os.environ['RS_TOOLSROOT']
|
|
if not tools_root_path:
|
|
logger.log("'RS_TOOLSROOT' path not found in environment", LogSeverity.ERROR)
|
|
return False
|
|
|
|
ruby_path = os.environ['RUBYLIB']
|
|
if not ruby_path:
|
|
logger.log("'RUBYLIB' path not found in environment", LogSeverity.ERROR)
|
|
return False
|
|
|
|
# Init package paths
|
|
package_path_release_orbis = os.path.join(ruby_path, r'util\ragebuilder\package_audio_orbis_release.rbs')
|
|
package_path_main_orbis = os.path.join(ruby_path, r'util\ragebuilder\package_audio_orbis.rbs')
|
|
package_path_release_durango = os.path.join(ruby_path, r'util\ragebuilder\package_audio_durango_release.rbs')
|
|
package_path_main_durango = os.path.join(ruby_path, r'util\ragebuilder\package_audio_durango.rbs')
|
|
package_path_release_win64 = os.path.join(ruby_path, r'util\ragebuilder\package_audio_win64_release.rbs')
|
|
package_path_main_win64 = os.path.join(ruby_path, r'util\ragebuilder\package_audio_win64.rbs')
|
|
|
|
# Init rage builder path - use rage builder gen9 for gen9 platforms
|
|
if platform == 'XBOXSERIES' or platform == 'PS5':
|
|
rage_builder_path = os.path.join(tools_root_path, r'bin\RageBuilderGen9\ragebuilder_Release_gen9_SGA.exe')
|
|
else:
|
|
rage_builder_path = os.path.join(tools_root_path, r'bin\ragebuilder_x64_0378.exe')
|
|
|
|
proj_root = os.environ['RS_PROJROOT']
|
|
if not proj_root:
|
|
logger.log("'RS_PROJROOT' path not found in environment", LogSeverity.ERROR)
|
|
return False
|
|
|
|
# Init audio path
|
|
audio_path = os.path.join(proj_root, 'audio', branch, 'staging')
|
|
|
|
# Init config dir
|
|
config_dir = os.path.join(audio_path, platform, 'config')
|
|
|
|
if not os.path.exists(config_dir):
|
|
logger.log("Creating path: %s" % config_dir, LogSeverity.INFO)
|
|
os.makedirs(config_dir)
|
|
|
|
# Init packlist paths (file may not exist locally)
|
|
packlist_path_main = os.path.join(config_dir, 'packlist.txt')
|
|
logger.log("Using main packlist path: %s" % packlist_path_main, LogSeverity.INFO)
|
|
packlist_path_release = os.path.join(config_dir, 'packlist_rel.txt')
|
|
logger.log("Using release packlist path: %s" % packlist_path_release, LogSeverity.INFO)
|
|
|
|
# Init input path
|
|
input_path = os.path.join(audio_path, platform, 'sfx')
|
|
if not os.path.exists(input_path):
|
|
logger.log("Path does not exist: %s" % input_path, LogSeverity.ERROR)
|
|
return False
|
|
logger.log("Using input path: %s" % input_path, LogSeverity.INFO)
|
|
|
|
if branch is None:
|
|
rpf_root_path = RPF_ROOT_PATH.replace(r'{branch}', DEFAULT_BRANCH)
|
|
else:
|
|
rpf_root_path = RPF_ROOT_PATH.replace(r'{branch}', branch)
|
|
|
|
rpf_source_path = os.path.join(rpf_root_path, output_platform_name, 'audio')
|
|
|
|
if not os.path.exists(rpf_root_path):
|
|
try:
|
|
os.makedirs(rpf_root_path)
|
|
except:
|
|
logger.log("Failed to create directory: %s" % rpf_root_path, LogSeverity.ERROR)
|
|
return False
|
|
|
|
# Init output path
|
|
audio_output_path = os.path.join(rpf_root_path, output_platform_name, 'audio')
|
|
if not os.path.exists(audio_output_path):
|
|
logger.log("Path does not exist - creating directory: %s" % audio_output_path, LogSeverity.INFO)
|
|
try:
|
|
os.makedirs(audio_output_path)
|
|
except:
|
|
logger.log("Failed to create directory: %s" % audio_output_path, LogSeverity.ERROR)
|
|
return False
|
|
logger.log("Using audio output path: %s" % audio_output_path, LogSeverity.INFO)
|
|
|
|
sfx_output_path = os.path.join(audio_output_path, 'sfx')
|
|
if not os.path.exists(sfx_output_path):
|
|
logger.log("Path does not exist - creating directory: %s" % sfx_output_path, LogSeverity.INFO)
|
|
try:
|
|
os.makedirs(sfx_output_path)
|
|
except:
|
|
logger.log("Failed to create directory: %s" % sfx_output_path, LogSeverity.ERROR)
|
|
return False
|
|
logger.log("Using sfx output path: %s" % sfx_output_path, LogSeverity.INFO)
|
|
|
|
return True
|
|
|
|
def generate_rpfs(rebuild, platform, changeListNumber):
|
|
global input_path
|
|
global sfx_output_path
|
|
global package_path
|
|
global p4
|
|
|
|
if rebuild:
|
|
logger.log("Generating all audio RPF files..", LogSeverity.INFO)
|
|
else:
|
|
logger.log("Generating latest audio RPF files..", LogSeverity.INFO)
|
|
|
|
# Open pack list file for writing and overwrite previous data
|
|
pack_list_file_main = open(packlist_path_main, 'w+')
|
|
pack_list_file_release = open(packlist_path_release, 'w+')
|
|
|
|
# Generate RPFs for files in each pack (ie sub-dir) in input_path
|
|
for path, packs, files in os.walk(input_path):
|
|
for pack in packs:
|
|
|
|
# Add pack to dev file list (if required)
|
|
skip_for_dev = False
|
|
for except_pattern in IGNORE_EXCEPTION_PACKS_LIST:
|
|
if re.match(except_pattern, pack, re.IGNORECASE):
|
|
skip_for_dev = False
|
|
break
|
|
else:
|
|
for pattern in DEV_IGNORE_PACKS_LIST:
|
|
if re.match(pattern, pack, re.IGNORECASE):
|
|
logger.log("Skipping pack for dev pack list: %s" % pack, LogSeverity.INFO)
|
|
skip_for_dev = True
|
|
break
|
|
|
|
if not skip_for_dev:
|
|
pack_list_file_main.write("%s\n" % pack)
|
|
|
|
# Add pack to release file list (if required)
|
|
skip_for_rel = False
|
|
for except_pattern in IGNORE_EXCEPTION_PACKS_LIST:
|
|
if re.match(except_pattern, pack, re.IGNORECASE):
|
|
skip_for_rel = False
|
|
break
|
|
else:
|
|
for pattern in RELEASE_IGNORE_PACKS_LIST[platform.upper()]:
|
|
if re.match(pattern, pack, re.IGNORECASE):
|
|
logger.log("Skipping pack for release pack list: %s" % pack, LogSeverity.INFO)
|
|
skip_for_rel = True
|
|
break
|
|
|
|
if not skip_for_rel:
|
|
pack_list_file_release.write("%s\n" % pack)
|
|
|
|
if not rebuild and not pack_requires_build(os.path.join(path, pack), pack):
|
|
# Skip current pack if build not required and
|
|
# process not marked for full rebuild
|
|
logger.log("Skipping pack - build not required: %s" % pack, LogSeverity.INFO)
|
|
continue
|
|
|
|
# Init build params
|
|
logger.log("Building pack %s..." % pack, LogSeverity.INFO)
|
|
input_pack_path = os.path.join(input_path, pack) + '\\'
|
|
output_file = os.path.join(sfx_output_path, pack) + '.rpf'
|
|
|
|
if platform.upper() == 'PS4' or platform.upper() == 'PS5':
|
|
package_path = package_path_main_orbis
|
|
if platform.upper() == 'XBOXONE' or platform.upper() == 'XBOXSERIES':
|
|
package_path = package_path_main_durango
|
|
if platform.upper() == 'PC':
|
|
package_path = package_path_main_win64
|
|
|
|
# checkout output file
|
|
if not p4.checkout(output_file, changeListNumber):
|
|
return False
|
|
|
|
# Run build command
|
|
#cmd = r'%s %s -pack %s -rootpath %s -extignore .rpf -nameheapshift=1' % (rage_builder_path, package_path, output_file, input_pack_path)
|
|
cmd = r'%s %s -pack %s -rootpath %s -extignore .rpf' % (rage_builder_path, package_path, output_file, input_pack_path)
|
|
logger.log("Running cmd: %s" % cmd, LogSeverity.INFO)
|
|
if os.system(cmd) != 0:
|
|
logger.log("Failed to successfully run command: %s" % cmd, LogSeverity.ERROR)
|
|
return False
|
|
|
|
pack_list_file_main.close()
|
|
pack_list_file_release.close()
|
|
|
|
return True
|
|
|
|
|
|
def pack_requires_build(pack_path, pack_name):
|
|
global sfx_output_path
|
|
|
|
rpf_path = '%s.rpf' % os.path.join(sfx_output_path, pack_name)
|
|
|
|
# If output file doesn't exist, it needs to be built
|
|
if not os.path.exists(rpf_path):
|
|
return True
|
|
|
|
for file in os.listdir(pack_path):
|
|
# Only interested in AWC files
|
|
if file.lower().endswith('.awc'):
|
|
awc_path = os.path.join(pack_path, file)
|
|
# If AWC file is newer than RPF file, it needs to be built
|
|
if os.stat(awc_path).st_mtime > os.stat(rpf_path).st_mtime:
|
|
return True
|
|
|
|
return False
|
|
|
|
|
|
def generate_audio_rpf(platform, changeListNumber, release=False):
|
|
global audio_path
|
|
global audio_output_path
|
|
global rage_builder_path
|
|
global package_path
|
|
global p4
|
|
|
|
root_path = os.path.join(audio_path, platform)
|
|
|
|
if release:
|
|
output_file = 'audio_rel.rpf'
|
|
if platform.upper() == 'PS4' or platform.upper() == 'PS5':
|
|
package_path = package_path_release_orbis
|
|
if platform.upper() == 'XBOXONE' or platform.upper() == 'XBOXSERIES':
|
|
package_path = package_path_release_durango
|
|
if platform.upper() == 'PC':
|
|
package_path = package_path_release_win64
|
|
else:
|
|
output_file = 'audio.rpf'
|
|
if platform.upper() == 'PS4' or platform.upper() == 'PS5':
|
|
package_path = package_path_main_orbis
|
|
if platform.upper() == 'XBOXONE' or platform.upper() == 'XBOXSERIES':
|
|
package_path = package_path_main_durango
|
|
if platform.upper() == 'PC':
|
|
package_path = package_path_main_win64
|
|
|
|
pack = os.path.join(audio_output_path, output_file)
|
|
|
|
# checkout output file
|
|
if not p4.checkout(pack, changeListNumber):
|
|
return False
|
|
|
|
cmd = r'%s %s -pack %s -rootpath %s\ -extignore .awc' % (rage_builder_path, package_path, pack, root_path)
|
|
#cmd = r'%s %s -pack %s -rootpath %s\ -extignore .awc -nameheapshift=1' % (rage_builder_path, package_path, pack, root_path)
|
|
|
|
logger.log("Running cmd: %s" % cmd, LogSeverity.INFO)
|
|
if os.system(cmd) != 0:
|
|
logger.log("Failed to successfully run command: %s" % cmd, LogSeverity.ERROR)
|
|
return False
|
|
|
|
return True
|
|
|
|
|
|
def set_working_path(path):
|
|
global working_path
|
|
|
|
# Change working path if required
|
|
if working_path != path:
|
|
working_path = path
|
|
msg = "Setting working path as %s" % path
|
|
logger.log(msg, LogSeverity.INFO)
|
|
os.chdir(path)
|
|
|
|
def failed():
|
|
logger.save()
|