Push 0.10.0

This commit is contained in:
Oracle 2026-05-18 16:31:58 +02:00
parent 266f3fc76d
commit 12c05afa57
Signed by: Oracle
SSH key fingerprint: SHA256:x4/RtnjUyuHkdvmwNDsWSfcfF1V5PNr3OpriZqOvCX8
25 changed files with 2016 additions and 645 deletions

View file

@ -1,7 +1,7 @@
# -*- coding: utf8 -*-
# libray - Libre Blu-Ray PS3 ISO Tool
# Copyright © 2018 -2021 Nichlas Severinsen
# Copyright © 2018 - 2024 Nichlas Severinsen
#
# This file is part of libray.
#
@ -20,105 +20,104 @@
try:
from libray import core
from libray import core
except ImportError:
import core
import core
class SFO:
"""Class for handling .sfo files
"""Class for handling .sfo files
Attributes:
magic: Magic header
version: .SFO version
key_table_start: Absolute offset for key_table in .SFO
data_table_start: Absolute offset for index_table in .SFO
tables_entries: Number of entries in index_table and key_table
key_data: Parsed keys and data tables from .SFO transformed into dict
"""
Attributes:
magic: Magic header
version: .SFO version
key_table_start: Absolute offset for key_table in .SFO
data_table_start: Absolute offset for index_table in .SFO
tables_entries: Number of entries in index_table and key_table
key_data: Parsed keys and data tables from .SFO transformed into dict
"""
def __init__(self, fp):
def __init__(self, fp):
self.file_start = fp.tell()
self.file_start = fp.tell()
# Header
# Header
self.magic = fp.read(4)
self.version = fp.read(4)
self.key_table_start = core.to_int(fp.read(4), 'little')
self.data_table_start = core.to_int(fp.read(4), 'little')
self.tables_entries = core.to_int(fp.read(4), 'little')
self.magic = fp.read(4)
self.version = fp.read(4)
self.key_table_start = core.to_int(fp.read(4), 'little')
self.data_table_start = core.to_int(fp.read(4), 'little')
self.tables_entries = core.to_int(fp.read(4), 'little')
# Index table
# Index table
index_table = []
index_table = []
for _ in range(0, self.tables_entries):
index_table.append({
'key_offset': core.to_int(fp.read(2), 'little'),
'data_fmt': fp.read(2),
'data_len': core.to_int(fp.read(4), 'little'),
'data_max_len': core.to_int(fp.read(4), 'little'),
'data_offset': core.to_int(fp.read(4), 'little'),
})
for _ in range(0, self.tables_entries):
index_table.append({
'key_offset': core.to_int(fp.read(2), 'little'),
'data_fmt': fp.read(2),
'data_len': core.to_int(fp.read(4), 'little'),
'data_max_len': core.to_int(fp.read(4), 'little'),
'data_offset': core.to_int(fp.read(4), 'little'),
})
# Key table
# Key table
key_table = []
key_table = []
for i in range(0, self.tables_entries):
for i in range(0, self.tables_entries):
# Seek to absolute offset + relative offset of key
# Seek to absolute offset + relative offset of key
fp.seek(self.file_start + self.key_table_start + index_table[i]['key_offset'])
fp.seek(self.file_start + self.key_table_start +
index_table[i]['key_offset'])
# Read key string until nullbyte
# Read key string until nullbyte
key = ''
key = ''
while True:
while True:
data = fp.read(1)
data = fp.read(1)
if data == b'\x00':
break
if data == b'\x00':
break
key += data.decode('utf8')
key += data.decode('utf8')
key_table.append(key)
key_table.append(key)
# Data table
# Data table
self.key_data = {}
self.key_data = {}
for i in range(0, self.tables_entries):
for i in range(0, self.tables_entries):
# Seek to absolute offset + relative offset of data
# Seek to absolute offset + relative offset of data
fp.seek(self.file_start + self.data_table_start + index_table[i]['data_offset'])
fp.seek(self.file_start + self.data_table_start + index_table[i]['data_offset'])
if index_table[i]['data_fmt'] == b'\x04\x02': #UTF8
data = fp.read(index_table[i]['data_len'] - 1).decode('utf8')
elif index_table[i]['data_fmt'] == b'\x04\x04': #int32
data = core.to_int(fp.read(index_table[i]['data_len']), 'little')
else: # Meh
data = fp.read(index_table[i]['data_len'])
if index_table[i]['data_fmt'] == b'\x04\x02': # UTF8
data = fp.read(index_table[i]['data_len'] - 1).decode('utf8')
elif index_table[i]['data_fmt'] == b'\x04\x04': # int32
data = core.to_int(
fp.read(index_table[i]['data_len']), 'little')
else: # Meh
data = fp.read(index_table[i]['data_len'])
self.key_data[key_table[i]] = data
self.key_data[key_table[i]] = data
def __getitem__(self, key):
"""Overload [] so we can directly select data using key from .SFO"""
return self.key_data[key]
def __getitem__(self, key):
"""Overload [] so we can directly select data using key from .SFO"""
return self.key_data[key]
def print_info(self):
print('Magic:', self.magic)
print('Version: ', self.version)
print('key_table_start:', self.key_table_start)
print('data_table_start:', self.data_table_start)
print('tables_entries:', self.tables_entries)
def print_info(self):
print('Magic:', self.magic)
print('Version: ', self.version)
print('key_table_start:', self.key_table_start)
print('data_table_start:', self.data_table_start)
print('tables_entries:', self.tables_entries)
print(self.key_data)
print(self.key_data)