#!/usr/bin/ruby require 'zlib' def usage STDERR.puts "Tool for building and extracting Oneshot scripts file(xScripts.rxdata)" STDERR.puts "usage: rpgscript.rb scripts_dir game_dir [x]" exit 1 end usage if ARGV.length < 2 scripts_dir = ARGV[0] game_dir = ARGV[1] if ARGV.length >= 3 usage if ARGV[2] != 'x' extract = true else extract = false end # Determine version of game engine game_data_dir = File.join(game_dir, 'Data') unless Dir.exist? game_data_dir STDERR.puts "error: #{game_dir} does not have a Data subdirectory" exit 1 end target_path = nil Dir.entries(game_data_dir).each do |e| ext = File.extname(e) if ext =~ /\.r[xv]data2?/ target_path = File.join(game_data_dir, 'xScripts' + ext) break end end unless target_path STDERR.puts "warning: could not determine game engine version, assuming XP" target_path = File.join(game_data_dir, 'xScripts.rxdata') end # Generate path of script list list_path = File.join(scripts_dir, '_scripts.txt') if extract # Make sure the script directory exists Dir.mkdir(scripts_dir) unless Dir.exist? scripts_dir # Keep track of names of scripts extracted so we can warn about duplicates names = Hash.new(0) # Read scripts File.open(target_path, 'rb') do |fin| File.open(list_path, 'w') do |flist| Marshal.load(fin).each_with_index do |script, index| name = script[1].strip data = Zlib::Inflate.inflate(script[2]).rstrip .gsub(/[ \t]*(?:$|\r\n?)/, "\n") # Make sure this file doesn't already exist if name.empty? if data.empty? || data == "\n" flist.puts next else name = 'UNTITLED' end end names[name] += 1 if names[name] > 1 name << " (#{names[name]})" end if data.empty? || data == "\n" # Treat this like a comment flist.puts('# ' + name) else # Write to file order list flist.puts(name) # Write script file File.open(File.join(scripts_dir, name + '.rb'), 'wb') do |fout| fout.write(data) end end end end end puts "#{target_path} extracted." else # Write scripts scripts = [] IO.foreach(list_path) do |name| name.strip! next if name.empty? || name.start_with?('#') data = File.read(File.join(scripts_dir, name + '.rb')).rstrip.gsub("\n", "\r\n") script = Array.new(3) script[0] = 0 script[1] = name script[2] = Zlib.deflate(data) scripts << script end File.open(target_path, 'wb') { |f| f.write(Marshal.dump(scripts)) } puts "#{target_path} written." end