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

197 lines
8.5 KiB
Ruby
Executable File

#
# File:: data_compare_merge_images.rb
# Description:: Performs map comparisons on images for the E1/E2 disc build.
#
# Author:: Marissa Warner-Wu <marissa.warner-wu@rockstarnorth.com>
# Date:: 13 August 2009
#
#-----------------------------------------------------------------------------
# Uses
#-----------------------------------------------------------------------------
require 'pipeline/config/projects'
require 'pipeline/config/project'
require 'pipeline/os/getopt'
require 'pipeline/os/path'
require 'pipeline/projectutil/data_compare_merge'
require 'pipeline/util/string'
include Pipeline
#-----------------------------------------------------------------------------
# Constants
#-----------------------------------------------------------------------------
OPTIONS = [
[ '--rootproj', '-r', OS::Getopt::REQUIRED, 'root control project' ],
[ '--rootbranch', '-b', OS::Getopt::REQUIRED, 'root control project branch' ],
[ '--epproj', '-e', OS::Getopt::REQUIRED, 'episodic project' ],
[ '--epbranch', '-n', OS::Getopt::REQUIRED, 'episodic project branch' ],
[ '--image', '-i', OS::Getopt::REQUIRED, 'single image name to process' ],
[ '--output', '-o', OS::Getopt::REQUIRED, 'root output directory' ],
[ '--help', '-h', OS::Getopt::BOOLEAN, 'display usage information' ]
]
# Duplicate files to be removed from images
REMOVE_HASH = {
'platformimg:/data/maps/props/lev_des/minigame.img' => [ 'cj_mobile_3.xdr', 'cj_mobile_hand_1.xdr' ],
'platformimg:/data/maps/props/street/amenitie.img' => [ 'bm_tollbooth.xtd' ],
}
# Files which should be ignored during processing
EXCLUDE_FILES = ['public_3']
#-----------------------------------------------------------------------------
# Implementation
#-----------------------------------------------------------------------------
if ( __FILE__ == $0 ) then
begin
g_AppName = OS::Path::get_basename( __FILE__ )
g_Log = Log.new( g_AppName )
g_Config = Pipeline::Config::instance( )
#---------------------------------------------------------------------
# Parse Command Line
#---------------------------------------------------------------------
g_Opts, g_Trailing = OS::Getopt::getopts( OPTIONS )
if ( g_Opts['help'] ) then
puts OS::Getopt::usage( OPTIONS )
exit( 1 )
end
g_RootProjectName = ( nil == g_Opts['rootproj'] ) ? '' : g_Opts['rootproj']
root_project_exists = ( g_Config.projects.has_key?( g_RootProjectName ) )
if ( not root_project_exists ) then
puts OS::Getopt::usage( OPTIONS )
puts "\nError root project: #{g_RootProjectName} does not exist or its configuration is unreadable."
exit( 2 )
end
g_EpProjectName = ( nil == g_Opts['epproj'] ) ? '' : g_Opts['epproj']
ep_project_exists = ( g_Config.projects.has_key?( g_EpProjectName ) )
if ( not ep_project_exists ) then
puts OS::Getopt::usage( OPTIONS )
puts "\nError episodic project: #{g_EpProjectName} does not exist or its configuration is unreadable."
exit( 3 )
end
g_RootProject = g_Config.projects[ g_RootProjectName ]
g_EpProject = g_Config.projects[ g_EpProjectName ]
if ( not g_RootProject.enabled ) then
puts "\nError root project: #{g_RootProjectName} is not enabled on this machine. Re-run installer."
exit( 4 )
end
if ( not g_EpProject.enabled ) then
puts "\nError episodic project: #{g_EpProjectName} is not enabled on this machine. Re-run installer."
exit( 5 )
end
g_RootProject.load_config( )
g_EpProject.load_config( )
g_RootBranchName = ( nil == g_Opts['rootbranch'] ) ? g_RootProject.default_branch : g_Opts['rootbranch']
if ( not g_RootProject.branches.has_key?( g_RootBranchName ) ) then
puts "\nError root project: #{g_RootProjectName} does not have a branch called #{g_RootBranchName}."
exit( 6 )
end
g_RootBranch = g_RootProject.branches[ g_RootBranchName ]
g_EpBranchName = ( nil == g_Opts['epbranch'] ) ? g_EpProject.default_branch : g_Opts['epbranch']
if ( not g_EpProject.branches.has_key?( g_EpBranchName ) ) then
puts "\nError episodic project: #{g_EpProjectName} does not have a branch called #{g_EpBranchName}."
exit( 7 )
end
g_EpBranch = g_EpProject.branches[ g_EpBranchName ]
g_TargetName = 'xbox360'
g_Image = ( nil == g_Opts['image'] ) ? nil : g_Opts['image']
# Get the output path
g_OutputDir = ( nil == g_Opts['output'] ) ? File::expand_path( '.' ) : OS::Path::normalise(g_Opts['output'])
# If the last character is a slash then remove it
if g_OutputDir[-1].eql? 47
g_OutputDir.chop!
end
puts "Project 1: #{g_RootProject.uiname} #{g_RootBranch.name}"
puts "Project 2: #{g_EpProject.uiname} #{g_EpBranch.name}"
#---------------------------------------------------------------------
# Comparison
#---------------------------------------------------------------------
start_time = Time.now()
# Make the output directory if it doesn't already exist
::FileUtils::mkdir_p( g_OutputDir ) unless ( ::File::directory?( g_OutputDir ) )
# Compare map data
puts "\nComparing map images...\n\n"
ProjectUtil::data_compare_merge_maps_images( g_RootBranch, g_EpBranch, g_TargetName, g_OutputDir, EXCLUDE_FILES, g_Image ) do |filename, new_filename|
# Copy files from the comparison to the output directory
if OS::Path::starts_with( new_filename, g_OutputDir )
puts "FIRST BRANCH"
dst_filename = new_filename.gsub( g_OutputDir, OS::Path::combine( 'x:', 'gta_e1', 'build', 'dev_disc', 'xbox360', 'independent', 'data', 'maps' ) )
else
puts "SECOND BRANCH"
dst_filename = new_filename.gsub( OS::Path::combine( g_RootBranch.independent, 'data', 'maps' ), OS::Path::combine( 'x:', 'gta_e1', 'build', 'dev_disc', 'xbox360', 'independent', 'data', 'maps' ) )
end
dst_path = OS::Path::get_directory( dst_filename )
FileUtils::mkdir_p( dst_path ) unless ( ::File::directory?( dst_path ) )
puts "Copying file: #{filename}"
puts "\tto #{dst_filename}"
puts "FILENAME: #{filename}"
puts "NEW : #{new_filename}"
puts "DST : #{dst_filename}"
if ( ::File::exists?( new_filename ) ) then
FileUtils::rm( dst_filename ) if ::File::exists?( dst_filename )
FileUtils::cp( new_filename, dst_filename, :preserve => true )
FileUtils::chmod( 0666, dst_filename )
else
puts "WARNING: #{filename} does not exist for copying."
end
end #data_compare_merge_maps_images
# Only perform post-processing if we aren't running on a single image
if g_Image.nil?
# Copy over episodic-only files
puts "Post-Processing: copying episodic-only files..."
ep_files = OS::FindEx::find_files( OS::Path::combine( g_EpBranch.independent, 'data', 'maps', 'props', '*.img' ) )
ep_files.concat( OS::FindEx::find_files( OS::Path::combine( g_EpBranch.independent, 'data', 'maps', 'interiors', '*.img' ) ) )
ep_files.delete_if { |file| EXCLUDE_FILES.include?( OS::Path::get_basename( file ) ) }
ep_files.each do |new_filename|
# Construct destination path
dst_filename = new_filename.gsub( OS::Path::combine( g_EpBranch.independent, 'data', 'maps' ), OS::Path::combine( 'x:', 'gta_e1', 'build', 'dev_disc', 'xbox360', 'independent', 'data', 'maps' ) )
file = OS::Path::get_filename( dst_filename )
dst_filename = OS::Path::combine( OS::Path::get_directory( dst_filename ), 'extra', file )
dst_path = OS::Path::get_directory( dst_filename )
FileUtils::mkdir_p( dst_path ) unless ( ::File::directory?( dst_path ) )
# Copy episodic files to output directory
puts "Copying file: #{new_filename}"
puts "\tto #{dst_filename}"
puts "FILENAME: #{new_filename}"
puts "NEW : #{new_filename}"
puts "DST : #{dst_filename}"
if ( ::File::exists?( new_filename ) ) then
FileUtils::rm(dst_filename) if ::File::exists?( dst_filename )
FileUtils::cp( new_filename, dst_filename, :preserve => true )
FileUtils::chmod( 0666, dst_filename )
else
puts "WARNING: #{filename} does not exist for copying."
end
end #ep_files.each
# Remove duplicate files
puts "Post-Processing: removing duplicate files from images..."
g_OutputIndependent = OS::Path::combine( 'x:', 'gta_e1', 'build', 'dev_disc', 'xbox360', 'independent' )
ProjectUtil::data_compare_merge_remove_duplicates( g_RootBranch, g_TargetName, g_OutputIndependent, REMOVE_HASH )
end #if g_Image.nil?
puts "Time taken: #{Time.now() - start_time}s"
end
end
# data_compare_merge_images.rb