Skip to content

Instantly share code, notes, and snippets.

@drizzt
Created March 25, 2011 22:33
Show Gist options
  • Save drizzt/887780 to your computer and use it in GitHub Desktop.
Save drizzt/887780 to your computer and use it in GitHub Desktop.
require 'bindata'
require 'find'
class Sfo
class SfoHeader < BinData::Record
string :magic, :length => 4, :check_value => "\x00PSF"
uint32be :versfidn, :check_value => 0x01010000
uint32le :key_table_offset
uint32le :data_table_offset
uint32le :number_of_items
array :items, :initial_length => lambda { number_of_items - 1 } do
struct do
uint16le :key_offset
uint8 :unknown, :check_value => 0x04
uint8 :type, :check_value => lambda { value == 0 or value == 2 or value ==4 }
uint32le :data_size
uint32le :padded_size
uint32le :data_offset
end
end
end
def initialize(io)
if String === io
if io.ascii_only? and File.exists?(io)
@io = File.new(io, File::RDONLY | File::BINARY)
else
@io = StringIO.new(io)
end
elsif File === io or StringIO === io
@io = io
@io.binmode
else
raise ArgumentError, "io must be a File, String or StringIO"
end
@sfo_hdr = SfoHeader.read(@io)
end
def [](item)
items[item.to_sym]
end
def items
@items ||=
Hash[
@sfo_hdr.items.collect do |sfo_item_hdr|
data_offset = @sfo_hdr.data_table_offset.to_i + sfo_item_hdr.data_offset.to_i
key_offset = @sfo_hdr.key_table_offset.to_i + sfo_item_hdr.key_offset.to_i
@io.seek(key_offset, IO::SEEK_SET)
key = BinData::Stringz.read(@io)
@io.seek(data_offset, IO::SEEK_SET)
if (sfo_item_hdr.type == 2) # Text
Array[key.to_sym, @io.read(sfo_item_hdr.data_size - 1)]
elsif (sfo_item_hdr.type == 4) # Number (32-bit little endian)
Array[key.to_sym, BinData::Int32le.read(@io).to_i]
end
end
]
end
end
ARGV.each do |arg|
Find.find(arg) do |path|
if path[/PS3_GAME\/PARAM.SFO$/]
sfo_hdr = Sfo.new(path)
puts "#{sfo_hdr['TITLE_ID']} #{sfo_hdr['TITLE']}"
Find.prune
end
end
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment