RenRestore extracts files from RenPy's RPA archives. It supports various RPA formats, both official and unofficial. You can implement custom formats by inheriting ArchiveFormat
and adding them to an ArchiveFormatRegistry
. The RenRestore
class uses this registry to detect and handle different archive formats.
The AutoRegistry
loads all available formats (with .rpaf.py
extension) from the /RenRestore/ArchiveFormats/Plugins/
directory by default.
Currently, RenRestore is only available as source code.
import logging
from RenRestore import RenRestore
log = logging.getLogger("RenRestore")
log.addHandler(logging.StreamHandler())
log.setLevel(logging.DEBUG)
restorer = RenRestore(create_output_directory=True)
restorer.extract_files("scripts.rpa", "output")
import logging
from RenRestore import RenRestore, ArchiveFormat, ArchiveFormatRegistry
from typing import Dict, Iterable, Tuple, Optional, BinaryIO, Callable
log = logging.getLogger("RenRestore")
log.addHandler(logging.StreamHandler())
log.setLevel(logging.DEBUG)
class CustomArchiveFormat(ArchiveFormat):
def extract(self, index: Dict[str, Iterable[Tuple[int, int, bytes]]], archive: BinaryIO,
on_exception: Callable[[Exception], ...]) -> Iterable[Tuple[str, Iterable[bytes]]]:
pass
def index(self, archive: BinaryIO, offset_and_key: Optional[Tuple[int, int]]) -> Dict[
str, Iterable[Tuple[int, int, bytes]]]:
pass
def postprocess(self, source: BinaryIO) -> BinaryIO:
pass
def preprocess(self, source: BinaryIO) -> BinaryIO:
pass
def find_offset_and_key(self, archive: BinaryIO) -> Tuple[int, Optional[int]]:
pass
def detect(self, archive: BinaryIO) -> bool:
pass
registry = ArchiveFormatRegistry()
registry + CustomArchiveFormat # Yes, i know this is cursed, but currently the way to add an archive format to the registry.
restorer = RenRestore(create_output_directory=True, format_registry=registry)
restorer.extract_files("custom_archive.custom", "output")