elfish-tools/src/elfish/roe.py

48 lines
1.7 KiB
Python

"""Tools for parsing a ROE file."""
from os import SEEK_CUR, SEEK_SET
from os.path import basename, splitext
from struct import unpack
from .exceptions import InvalidROEFileError
from .utils import nibble_flip
class Roe:
"""The DNA of an electronic fish with an embedded icon."""
def __init__(self, name: str = "", author: str | None = None) -> None:
self.name: str = name
self.author: str | None = author
self.is_mutant: bool = False
self.unknowns: dict[str, bytes] = {}
@classmethod
def from_file(cls, filename: str) -> "Roe":
"""Factory for importing roe from a .ROE file."""
# Unlike .FSH files, the name comes from the filename itself. Since
# DOS was limited to the 8.3 naming convention, a fish's name has a
# forced limit of only eight characters.
name = splitext(basename(filename))[0][0:8]
roe = cls(name)
with open(filename, "rb") as rfile:
# First byte of file determines mutant status. Non-zero = mutant.
# Second byte is padding.
roe.is_mutant = unpack("?x", rfile.read(2))[0]
# Next two bytes are unknown.
roe.unknowns["00000002"] = unpack("2s", rfile.read(2))[0]
# Next sixteen bytes is a nibble-flipped encoding of the original
# author with a zero null termination byte.
author = ""
flipped_author = unpack("16s", rfile.read(16))[0]
for letter in flipped_author:
code = nibble_flip(letter)
if code == 0:
break
author += chr(code)
roe.author = author.upper()
return roe