Files
gtav-src/tools_ng/lib/util/data_rebuild_frag_tune.rb
T
2025-09-29 00:52:08 +02:00

195 lines
7.3 KiB
Ruby
Executable File

#
# File:: repack_frag_tune.rb
# Description:: Extract an IMG file, look up the *.ift's tune files, pack it in the *.ift
# and put them back in the original *.img file.
#
# Author:: Terry Litrenta <terry.litrenta@rockstartoronto.com>
# Date:: 30 July 2009
#
# This is my first Ruby script so please no snickering, laughing or downright knee slapping
# because of the numerous ways I am doing things. I will learn over time, but for now, lots of copy/pasting. :)
#
#----------------------------------------------------------------------------
# Uses
#----------------------------------------------------------------------------
require 'pipeline/gui/log_window'
require 'pipeline/config/projects'
require 'pipeline/os/getopt'
require 'pipeline/os/path'
require 'pipeline/projectutil/data_extract'
require 'pipeline/projectutil/data_convert'
require 'pipeline/resourcing/image'
require 'pipeline/util/rage'
require 'pipeline/win32/kernel32'
include Pipeline
#----------------------------------------------------------------------------
# Constants
#----------------------------------------------------------------------------
OPTIONS = [
[ '--project', '-p', Getopt::REQUIRED, 'project data to convert (e.g. jimmy, gta4_jpn).' ],
[ '--branch', '-b', Getopt::REQUIRED, 'project branch to convert (e.g. dev, dev_migrate).' ],
[ '--output', '-o', OS::Getopt::REQUIRED, 'output directory (root for multiple RPF extraction).' ],
[ '--overwrite', '-f', OS::Getopt::BOOLEAN, 'overwrite files if required.' ],
[ '--debug', '-d', OS::Getopt::BOOLEAN, 'debug mode toggle.' ],
[ '--help', '-h', OS::Getopt::BOOLEAN, 'display usage information.' ]
]
TRAILING_DESC = {
'files' => 'IMG files to extract.'
}
IMAGE_MOUNT = 'image:/'
PACK_MNT = "pack:/"
#----------------------------------------------------------------------------
# Implementation
#----------------------------------------------------------------------------
if ( __FILE__ == $0 ) then
begin
g_AppName = File::basename( __FILE__, '.rb' )
g_ProjectName = ''
g_Project = nil
g_Branch = ''
g_Config = Pipeline::Config.instance( )
#---------------------------------------------------------------------
# Parse Command Line
#---------------------------------------------------------------------
opts, trailing = OS::Getopt.getopts( OPTIONS )
if ( opts['help'] ) then
puts OS::Getopt.usage( OPTIONS, TRAILING_DESC )
exit( 1 )
end
g_Debug = opts['debug'].nil? ? false : true
Pipeline::Config::instance()::log_trace = g_Debug
# Force log output
Pipeline::Config::instance()::log_level = 2
Pipeline::Config::instance()::log_level = 1 if ( g_Debug )
g_Log = Log.new( g_AppName )
g_ProjectName = ( nil == opts['project'] ) ? '' : opts['project']
project_exists = ( g_Config.projects.has_key?( g_ProjectName ) )
if ( not project_exists ) then
puts OS::Getopt.usage( OPTIONS, TRAILING_DESC )
puts "\nError project: #{g_ProjectName} does not exist or its configuration is unreadable."
exit( 2 )
end
g_Project = g_Config.projects[ g_ProjectName ]
if ( not g_Project.enabled ) then
puts "\nError project: #{g_ProjectName} is not enabled on this machine. Re-run installer."
exit( 3 )
end
g_Project.load_config( )
g_BranchName = ( nil == opts['branch'] ) ? g_Project.default_branch : opts['branch']
if ( not g_Project.branches.has_key?( g_BranchName ) ) then
puts "\nError project: #{g_ProjectName} does not have a branch called #{g_BranchName}."
exit( 4 )
end
g_Branch = g_Project.branches[g_BranchName]
# Initialise RAGE (image file interface)
Pipeline::Config.instance.log_generate_html = false
r = Pipeline::RageUtils.new( g_Project, g_BranchName )
# Get the image file we want to extract and the path to extract to.
image = ::File::expand_path( trailing[0] )
path = OS::Path::combine(OS::Path.get_temp_directory(), OS::Path.get_basename(image))
# If we already have a directory with previous data then kill it and remake the directory, otherwise just create a new directory.
if ( File.directory?(path) ) then
FileUtils::remove_dir(path, true)
FileUtils.mkdir(path)
else
FileUtils.mkdir(path)
end
# Make sure the image file exists and it's not read-only.
if (not File.exists?(image)) then
puts "\nError: #{image} file does not exist."
exit(5)
end
if (not File.writable?(image)) then
puts "\nError: #{image} file is not writable. Please check it out from Perforce before running this."
exit(6)
end
# Get a list of all the files in the image file.
files = []
r.image.mount( image, IMAGE_MOUNT )
image_files = r.find_files( "#{IMAGE_MOUNT}*.*" )
image_files.each do |file|
files << file
end
r.image.unmount( image )
# Keep a variable to see if we actually need to rebuild the .img.
# If no .ift files are in the source image then there is no point to build or convert the final image.
bNeedToBuildImg = false
# Do the actual extraction of the needed files from the image.
exfiles = Resourcing::Image.extract( r, image, path, files )
# Go through the files extracted and just look at the .ift files.
exfiles.each do |f|
if (OS::Path.get_extension(f) == "ift") then
# Extract the *.ift RPF file.
ProjectUtil.data_extract_rpf( r, f, OS::Path::combine(path, OS::Path.get_basename(f)) )
# See if we have a tune file for this object in the data\fragments folder.
tuneFile = OS::Path::combine(g_Branch.common, "data", "fragments", OS::Path::get_basename(f)) + '.tune'
if (File.exists?(tuneFile)) then
# Copy the tune file from the data\fragments folder into our temp extracted folder.
r.util.copy_file(tuneFile, OS::Path::combine(path, OS::Path.get_basename(f), OS::Path.get_basename(f)) + '.tune')
# Start a new RPF file.
r.pack.start()
# Grab all the files in the temp IFT object directory.
newFileList = r.find_files(OS::Path::combine(path, OS::Path.get_basename(f)) + "\\*.*")
finalIFT = OS::Path::combine(path, OS::Path.get_basename(f)) + '.ift'
# Take all the files in the temp directory and add them to the new RPF file.
newFileList.each do |packFile|
fullFilename = OS::Path::combine(path, OS::Path.get_basename(f), packFile)
puts "Adding: #{fullFilename}\n"
r.pack.add(fullFilename, nil)
end
# Save the new RPF file with it's updated contents.
r.pack.save(finalIFT)
r.pack.close()
end
# We have a reason to live!
bNeedToBuildImg = true
end
end
if (bNeedToBuildImg) then
# Get a list of all the files in the temp directory minus the folders we extracted data too.
imageFileList = r.util.find_files("#{path}\\*.*", false, true).split(",")
# Overwrite the original image with the new one we built.
Resourcing::Image.create( r, image, imageFileList )
# Do the platform conversion of the new image file.
ProjectUtil::data_convert_file( image, true )
# Yay!
puts "\n\nCompleted: #{image}"
else
puts "\n\nNo rebuilding needed. No *.ift files exist in image"
end
rescue Exception => ex
exit( ex.status ) if ( 'exit' == ex.message )
puts "\n#{g_AppName} unhandled exception: #{ex.message}"
puts ex.backtrace.join("\n\t")
end
end