Files
gtav-src/tools_ng/script/coding/protection/rttihandling/parseForStrings.rb
T
2025-09-29 00:52:08 +02:00

181 lines
5.3 KiB
Ruby
Executable File

require 'getoptlong'
require 'Logger'
require 'pp'
require 'securerandom'
require 'fileutils'
# Setting up
RS_BUILDBRANCH = ENV['RS_BUILDBRANCH']
RS_TOOLSROOT = ENV['RS_TOOLSROOT']
PROTECTION_PATH = RS_TOOLSROOT + "/script/coding/protection"
GENERATED_PATH = PROTECTION_PATH + "/generated"
COMMON_RUBY_PATH = RS_TOOLSROOT + "/script/coding/protection/common/ruby"
$LOAD_PATH << COMMON_RUBY_PATH
require 'RsgLog'
LOG_SEVERITY_LEVEL = Logger::INFO
CURR_TIME = Time.now.strftime("%Y%m%d.%H.%M.%S")
class Parameters
attr_reader :game_path
attr_reader :debug
def initialize
@game_path = "" #false
@debug = false
@opts = GetoptLong.new(
[ '--help', '-h', GetoptLong::NO_ARGUMENT ],
[ '--path', '-p', GetoptLong::REQUIRED_ARGUMENT ],
[ '--debug', '-d', GetoptLong::NO_ARGUMENT ]
)
end
def PrintHelp()
puts "Usage: ruby protectit.rb -r <release> [options] "
puts " "
puts "-h --help Display this "
puts "-p --path Required. Full path to the executable."
end
def ParseArguments()
@opts.each do |opt, arg|
case opt
when '--help'
PrintHelp()
exit
when '--path'
@game_path = arg
when '--debug'
@debug = true
end
end
if(@game_path == "" || !File.exists?(@game_path))
puts "Invalid path to file \"" + @game_path + "\"\n\n"
PrintHelp()
exit
end
end
end
# Then our generated path
begin
Dir.mkdir(GENERATED_PATH)
rescue Exception =>e
puts e.message
end
log = RsgLog::RsgLog.instance()
log.SetParameters(GENERATED_PATH,CURR_TIME, LOG_SEVERITY_LEVEL)
# </commandLineArguments>
parameters = Parameters.new
parameters.ParseArguments()
gamePath = parameters.game_path
protectionPath = RS_TOOLSROOT + "/script/coding/protection"
rttiHandlingPath = protectionPath + "/rttihandling"
# Create our storage paths
replaceStorePath = rttiHandlingPath + "/replaceStrings.store"
warningStorePath = rttiHandlingPath + "/warningStrings.store"
# Build our strings command, and execute it
stringsPath = rttiHandlingPath + "/strings.exe"
stringsCmd = stringsPath + " --radix=d \"" + gamePath + "\""
stringsOutput = `#{stringsCmd}`
# Build our new file names
# Handle frozen status, if necessary
if (gamePath.frozen?)
gamePath = gamePath.dup
end
extension = File.extname(gamePath);
gamePath.slice! "#{extension}"
logPath = gamePath + ".stringWarnings.log"
replacementslogPath = gamePath + ".stringReplacements.log"
gameUnpatchedPath = gamePath + ".unpatchedstrings#{extension}"
gamePatchedPath = gamePath + ".patchedstrings#{extension}"
gamePath += "#{extension}"
replaceHash = Hash.new(0)
# Read from our storage files
replaceStoreLines = File.read(replaceStorePath)
warningStoreLines = File.read(warningStorePath)
# Create our replacing hash
replaceHash = Hash.new(0)
replaceStoreLines.each_line do |replaceLine|
stringsOutput.each_line do |stringsLine|
if ( stringsLine =~ /#{replaceLine}/)
splitString = stringsLine.split(' ')
replaceHash[splitString[0]] = splitString[1].strip;
end
end
end
# Create our replacing hash
warningHash = Hash.new(0)
warningStoreLines.each_line do |warningLine|
stringsOutput.each_line do |stringsLine|
if ( stringsLine =~ /#{warningLine}/i)
splitString = stringsLine.split(' ')
stringsLine.slice! "#{splitString[0]}"
warningHash[splitString[0]] = stringsLine.strip
end
end
end
# Read our game file in binary
gameBytes = open(gamePath, "rb") {|io| io.read }
# Create our log file handler
replacementslogFileHandle = File.open(replacementslogPath, 'w')
replacementslogFileHandle.write("List of detected strings, listed by their addresses and their full strings\n")
# Create our log file handler
logFileHandle = File.open(logPath, 'w')
logFileHandle.write("List of detected strings, listed by their addresses and their full strings\n")
# Create our output EXE
if parameters.debug == false
outFile = File.open(gamePatchedPath, 'wb')
end
i = 0
replaceHash.each {
|key, value|
stringToReplace = value
replacementslogFileHandle.write("#{stringToReplace} / #{key.to_s}\n")
if stringToReplace.length > 3
puts "Replacing #{stringToReplace}"
for j in 0...stringToReplace.length
myChar = 1 + rand(255 - 1)
gameBytes[key.to_i+j]=myChar.chr
end
end
}
warningHash.each {
|key, value|
stringToCheck = value
logFileHandle.write("0x" + key.hex.to_s + "\t" + value + "\n")
}
if parameters.debug == false
outFile.write(gameBytes)
end
# Close our handles
logFileHandle.close
if parameters.debug == false
outFile.close
# Now lets move the files to their appropriately names
FileUtils.mv(gamePath, gameUnpatchedPath)
FileUtils.mv(gamePatchedPath, gamePath)
end