Skip to content

Instantly share code, notes, and snippets.

@tlux
Last active August 29, 2015 14:07
Show Gist options
  • Select an option

  • Save tlux/67af92690dd715d1a24b to your computer and use it in GitHub Desktop.

Select an option

Save tlux/67af92690dd715d1a24b to your computer and use it in GitHub Desktop.
Freelancer Savegame Encoder/Decoder
# This script is based on the C++ implementation by Sherlog <sherlog@t-online.de> and Jor <flcodec@jors.net>
require 'active_support/all'
require 'singleton'
class FLCodec
include Singleton
class << self
delegate :encode, :decode, :load_file, :decode_file, :encode_file, to: :instance
end
class InvalidData < StandardError
def initialize
super "Stream contains invalid data"
end
end
HEADER = 'FLS1'.freeze
GENE = 'Gene'.freeze
def load_file(filename)
result = StringIO.new
File.open(filename, 'r') do |file|
self.decode(file, result)
end
result.string
end
def decode_file(src_path, dst_path = nil)
convert_file(:decode, src_path, dst_path, '.ini')
end
def decode(src_io, dst_io)
header = src_io.read(HEADER.length)
raise InvalidData unless header == HEADER
convert(src_io, dst_io)
end
def encode_file(src_path, dst_path = nil)
convert_file(:encode, src_path, dst_path, '.fl')
end
def encode(src_io, dst_io)
dst_io.write(HEADER)
convert(src_io, dst_io)
end
private
def convert(src_io, dst_io)
buffer = src_io.read
buffer.each_byte.with_index do |byte, index|
key = (GENE[index % GENE.length].ord + index) % 256
new_byte = byte ^ (key | 0x80)
dst_io.write(new_byte.chr)
end
true
end
def convert_file(type, src_path, dst_path, default_ext)
dst_path = src_path.chomp(File.extname(src_path)) + default_ext if dst_path.nil?
File.open(src_path, 'r') do |src_file|
File.open(dst_path, 'w') do |dst_file|
self.public_send(type, src_file, dst_file)
end
end
dst_path
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment