### Install pylivemaker from source with setup.py Source: https://pylivemaker.readthedocs.io/en/latest/_sources/installation.rst.txt After obtaining a copy of the source, run this command to install pylivemaker. ```console $ python setup.py install ``` -------------------------------- ### Set up local development environment Source: https://pylivemaker.readthedocs.io/en/latest/contributing.html Sets up a local development environment for pylivemaker using virtualenvwrapper, installs the package in development mode, installs development requirements, and installs pre-commit hooks. ```bash $ mkvirtualenv pylivemaker $ cd pylivemaker/ $ python setup.py develop $ pip install -r requirements_dev.txt $ pre-commit install ``` -------------------------------- ### get_menus method implementation Source: https://pylivemaker.readthedocs.io/en/latest/_modules/livemaker/lsb/lmscript.html Iterates through script commands to find menu start commands and builds menu objects, appending them with their line numbers. Skips menus that raise LiveMakerException. ```python menus = [] while True: try: if run_order: i, cmd, _ = next(gen) else: i, cmd = next(gen) except StopIteration: return menus if BaseSelectionMenu.is_menu_start(cmd): try: menu = make_menu(self, i, pylm=self.pylm) menus.append((cmd.LineNo, menu)) except LiveMakerException: pass ``` -------------------------------- ### get_menus method - return selection menus Source: https://pylivemaker.readthedocs.io/en/latest/_modules/livemaker/lsb/lmscript.html Returns a list of LiveNovel text selection menus. If run_order is True, uses walk() to get menus in game order; otherwise enumerates commands. ```python if run_order: gen = self.walk(unreachable=True) else: gen = enumerate(self.commands) ``` -------------------------------- ### livemaker.lsb.lmscript.LMScript.keys Source: https://pylivemaker.readthedocs.io/en/latest/livemaker.lsb.html Method to get the keys of the script's commands. ```APIDOC ## livemaker.lsb.lmscript.LMScript.keys ### Description Returns the keys of the script's commands. ### Method Method ### Signature `keys()` ``` -------------------------------- ### from_lsb_command class method Source: https://pylivemaker.readthedocs.io/en/latest/_modules/livemaker/lsb/menu.html Parses a LiveMaker script command to create a selection menu. Raises NotSelectionMenuError if the command is not a menu start or if required parameters are missing. Uses the menu file to load choices and resolves jump targets. ```python [docs] @classmethod def from_lsb_command(cls, lsb, start, pylm=None): try: cmd = lsb.commands[start] if not cls.is_menu_start(cmd): raise NotSelectionMenuError except IndexError: raise NotSelectionMenuError try: label = lsb.commands[start - 2] except IndexError: label = None params, next_cmd = cls._find_execute_params(lsb, start + 1) if not params: raise NotSelectionMenuError params = cls._parse_params(params) lpm_file = params["menu_file"].strip('"') try: choices = cls._choices_from_lpm(lpm_file, pylm=pylm) except FileNotFoundError: choices = None if not choices: raise NotSelectionMenuError jumps, next_cmd = cls._find_int_jumps(lsb, next_cmd) if not jumps: raise NotSelectionMenuError for text in jumps: target, index = jumps[text] jumps[text] = cls._resolve_int_jump(target, index, lsb), index menu = cls(lsb, lpm_file, label=label) for src_file, name in choices: try: target, target_index = jumps[name] except KeyError: logger.warning(f"{lpm_file} contains unreachable menu choice {name}") continue choice = LPMSelectionChoice(src_file, name, target, target_index) menu.add_choice(choice) return menu ``` -------------------------------- ### livemaker.lsb.lmscript.LMScript.items Source: https://pylivemaker.readthedocs.io/en/latest/livemaker.lsb.html Method to get the items of the script's commands. ```APIDOC ## livemaker.lsb.lmscript.LMScript.items ### Description Returns the items of the script's commands. ### Method Method ### Signature `items()` ``` -------------------------------- ### Dump LSB files with lmlsb dump Source: https://pylivemaker.readthedocs.io/en/latest/usage.html Dumps LSB files to text for inspection. The example uses the root game start chart node and the first user script. ```bash $ cd game_files $ lmlsb dump ゲームメイン.lsb > gamemain.txt $ lmlsb dump 00000001.lsb > 00000001.lsb.txt ``` -------------------------------- ### LiveMakerArchive.__init__ method Source: https://pylivemaker.readthedocs.io/en/latest/_modules/livemaker/archive.html Initializes a LiveMakerArchive instance. Validates mode is 'r' or 'w', opens the file if no file object is provided, and sets up internal attributes. Raises ValueError for invalid mode or missing name/fp. ```python def __init__(self, name=None, mode="r", fp=None, exe=None, split=False, version=DEFAULT_VERSION): self.closed = True if not name and not fp: raise ValueError("Nothing to open") modes = {"r": "rb", "w": "wb"} if mode not in modes: raise ValueError("mode must be 'r' or 'w'") self.mode = mode self._mode = modes[mode] if not fp: fp = open(name, self._mode) self._extfp = False else: if name is None and hasattr(fp, "name") and isinstance(fp.name, (str, bytes)): name = fp.name if hasattr(fp, "mode"): self._mode = fp.mode self._extfp = True self.fp = fp self.closed = False self.name = str(Path(name).resolve()) root, ext = os.path.splitext(self.name) self.filelist = [] self.name_info = {} ``` -------------------------------- ### LiveMakerArchive.__init__ Source: https://pylivemaker.readthedocs.io/en/latest/_modules/livemaker/archive.html Initializes a LiveMakerArchive instance. The constructor accepts a name, mode, file object, executable path, split flag, and version. It validates the mode and opens the archive file. ```APIDOC ## LiveMakerArchive.__init__ ### Description Initializes a LiveMakerArchive instance. The constructor accepts a name, mode, file object, executable path, split flag, and version. It validates the mode and opens the archive file. ### Method Constructor ### Signature `__init__(self, name=None, mode="r", fp=None, exe=None, split=False, version=DEFAULT_VERSION)` ### Parameters - **name** (str or path-like) - Optional - Pathname for the archive. If omitted, `fp` must be specified. - **mode** (str) - Optional - Either `'r'` to read from an existing archive or `'w'` to create a new file (overwriting an existing one). Defaults to `'r'`. - **fp** (file object) - Optional - If given, it will be used for reading and writing data. If it can be determined, `mode` will be overridden by `fp`'s mode. `fp` will be used from position 0. - **exe** (str) - Optional - Pathname for LiveMaker executable (`.exe`) file. If given and `mode` is `'w'`, the output file will be an executable with the archive appended to the end. If not given, the output file will be a standalone archive (`.dat` file). Does nothing when reading. - **split** (bool) - Optional - If opening in write mode and `split` is `True`, the archive data will be split into smaller files across 1GB boundaries. Has no effect in read mode or when writing an executable archive. - **version** (int) - Optional - Archive version, only applies to write mode. ### Notes - `fp` is not closed when `LiveMakerArchive` is closed. - `'a'` is an invalid `mode` for `LiveMakerArchive`. Archives cannot be modified in place. - When opened in write mode, the output archive file will not be written until `LMArchive.close()` is called. Entries are written to a temporary file, and upon `close()`, the exe (if it exists) and archive header are written to the output file, then the temporary file is copied to the end. ### Raises - `ValueError` - If neither `name` nor `fp` is provided, or if `mode` is not `'r'` or `'w'`. ``` -------------------------------- ### Install pylivemaker stable release with pip Source: https://pylivemaker.readthedocs.io/en/latest/_sources/installation.rst.txt Run this command in your terminal to install the most recent stable release of pylivemaker. This is the preferred method. ```console $ pip install pylivemaker ``` -------------------------------- ### lmpatch --help Source: https://pylivemaker.readthedocs.io/en/latest/cli.html Shows the command-line help for lmpatch, which replaces an existing LSB file in a LiveMaker executable. If the patched LSB file does not already exist, the command does nothing; a backup of the original executable is created. ```bash $ lmpatch --help Usage: lmpatch [OPTIONS] EXE_FILE PATCHED_LSB Patch a LiveMaker game. Any existing version of patched_lsb will be replaced in the specified LiveMaker executable. If a file with the same name as patched_lsb does not already exist, this will do nothing. A backup copy of the old exe will also be created. Options: --help Show this message and exit. ``` -------------------------------- ### livemaker.lsb.lmscript.LMScript.get_command Source: https://pylivemaker.readthedocs.io/en/latest/livemaker.lsb.html Method to get a command by line number. ```APIDOC ## livemaker.lsb.lmscript.LMScript.get_command ### Description Gets specified command by line number. ### Method Method ### Signature `get_command(line_no)` ### Parameters - **line_no** - The line number of the command. ### Returns tuple(cmd_index, cmd) - The command index and command object. ### Raises - **KeyError** - If the specified line_no does not exist in this LSB. ``` -------------------------------- ### LNSCompiler.get_starttag_text Source: https://pylivemaker.readthedocs.io/en/latest/livemaker.html Return full source of start tag: '<…>'. ```APIDOC ## get_starttag_text ### Description Return full source of start tag: '<…>'. ### Method instance method ### Signature get_starttag_text() ``` -------------------------------- ### galconvert --help Source: https://pylivemaker.readthedocs.io/en/latest/cli.html Shows the command-line help for galconvert, which converts GAL/GaleX images to formats supported by PIL/Pillow. Output format is determined by file extension; only the first frame is used for formats without multi-frame support, and direct conversion to GAL is not supported. ```bash galconvert --help Usage: galconvert [OPTIONS] INPUT_FILE OUTPUT_FILE Convert the image to another format. GAL(X) images can only be read (for conversion to JPEG/PNG/etc) at this time. Output format will be determined based on file extension. Options: -f, --force Overwrite output file if it exists. --help Show this message and exit. ``` -------------------------------- ### LMLivePrevMenu.to_lpm Source: https://pylivemaker.readthedocs.io/en/latest/livemaker.html Compiles the current settings into binary .lpm format. Returns the compiled binary data. ```APIDOC ## LMLivePrevMenu.to_lpm ### Description Compiles the current settings into binary .lpm format. Returns the compiled binary data. ### Method instance method ### Endpoint livemaker.lpm.LMLivePrevMenu.to_lpm ### Parameters None ### Response #### Success Response - **bytes** - Compiled .lpm binary data. ### Response Example ```python lpm_data = menu.to_lpm() ``` ``` -------------------------------- ### LMScript.__init__ Source: https://pylivemaker.readthedocs.io/en/latest/livemaker.lsb.html Constructor for the LMScript class. ```APIDOC ## LMScript(version=117, param_type=1, flags=0, call_name='', novel_params=[], command_params=[[]], commands=[], **kwargs) ### Description Creates a new LiveMaker script object. A LiveMaker script is a collection of LiveMaker novel commands. One LiveMaker/LiveNovel "Chart" will be serialized as one script file. ### Parameters - **version** (int) - Optional - Version number. If version is not in the range [MIN_LSB_VERSION, MAX_LSB_VERSION], this LMScript cannot be compiled into a binary LSB. - **param_type** - Optional - Unknown type flag (always 1?). - **flags** (int) - Optional - Unknown (always 0?). - **call_name** (str) - Optional - String name for calling this script (only used for documentation). - **novel_params** (iterable) - Optional - Iterable containing string descriptions for parameters that this script accepts (only used for documentation). - **command_params** (iterable of iterable of bool) - Optional - Two dimensional array of booleans specifying the command parameters are for Component type commands. (i.e. command_params[CommandType.BoxNew][PropertyType.PR_NAME] == True means that BoxNew takes a PR_NAME parameter.) - **commands** (iterable) - Optional - Iterable containing this script's Command objects. ### Raises - **BadLsbError** - If the specified LMScript would be invalid or unsupported. ``` -------------------------------- ### LNSTextLine initialization and position properties Source: https://pylivemaker.readthedocs.io/en/latest/_modules/livemaker/lsb/novel.html Initialize an LNSTextLine with position validation. Use when creating text lines for TpWord bodies. The read-only start and end attributes remain tied to the original TpWord body. Equality is based on start, end, and digest; string equality compares text attributes. ```python def __init__(self, text, start, end=None, name_label=None): super().__init__(text) self.name_label = name_label self._start = start if self._start < 0: raise ValueError("LNSTextLine start must be >= 0") if end is None: self._end = start + len(text) else: self._end = end if self._end <= start: raise ValueError("LNSTextLine end must be > start") ``` ```python @property def start(self): return self._start @property def end(self): return self._end ``` ```python def __hash__(self): return hash((self.start, self.end, self.digest)) def __lt__(self, other): return self.start < other.start and self.end < other.end [docs] def overlaps(self, other): return (self.start >= other.start and self.start < other.end) or ( self.end > other.start and self.end <= other.end ) ``` -------------------------------- ### lmlsb --help: list available commands Source: https://pylivemaker.readthedocs.io/en/latest/cli.html Shows the top-level help for the lmlsb CLI, listing all available subcommands (batchinsert, dump, edit, extract, extractcsv, extractmenu, insert, insertcsv, insertmenu, probe, validate) and the --version/--help options. ```bash $ lmlsb --help Usage: lmlsb [OPTIONS] COMMAND [ARGS]... Command-line tool for manipulating LSB scripts. Options: --version Show the version and exit. --help Show this message and exit. Commands: batchinsert Compile specified LNS script directory and insert it into the... dump Dump the contents of the specified LSB file(s) to stdout in a... edit Edit the specified command within an LSB file. extract Extract decompiled LiveNovel scripts from the specified input... extractcsv Extract text from the given LSB file to a CSV file. extractmenu Extract menu choices from the given LSB file to a CSV file. insert Compile specified LNS script and insert it into the specified... insertcsv Apply translated text lines from the given CSV file to given... insertmenu Apply translated menu choices from the given CSV file to... probe Output information about the specified LSB file in... validate Verify that the specified LSB file(s) can be processed. ``` -------------------------------- ### Clone pylivemaker repository from Github Source: https://pylivemaker.readthedocs.io/en/latest/_sources/installation.rst.txt Clone the public repository from Github to get the source code. ```console $ git clone git://github.com/pmrowla/pylivemaker ``` -------------------------------- ### BaseComponentCommand __init__ with Target Source: https://pylivemaker.readthedocs.io/en/latest/_modules/livemaker/lsb/command.html Initializes a command with a Target argument, converting construct.Container instances to LiveParser objects. ```python def __init__(self, Target=LiveParser(), **kwargs): super().__init__(**kwargs) if isinstance(Target, construct.Container): Target = LiveParser.from_struct(Target) self.args["Target"] = Target ``` -------------------------------- ### LiveMakerArchive.getinfo - get entry info by name Source: https://pylivemaker.readthedocs.io/en/latest/_modules/livemaker/archive.html Returns a LMArchiveInfo object for the entry with the specified name. Raises KeyError if the name does not exist in the archive. ```python def getinfo(self, name): """Return a `LMArchiveInfo` object for the entry with the specified name. Raises: KeyError: If `name` is not an entry in the archive. """ info = self.name_info.get(name) if info is None: raise KeyError("{} does not exist in archive.".format(name)) return info ``` -------------------------------- ### lmbmp --help Source: https://pylivemaker.readthedocs.io/en/latest/cli.html Shows the command-line help for lmbmp, which converts an image to BMP files for use with LiveMaker's BmpToGale tool. If the input has an alpha layer, a mask bitmap is generated; output files are named .bmp and -m.bmp. ```bash $ lmbmp --help Usage: lmbmp [OPTIONS] INPUT_FILE Convert image to BMP(s) which can be used with bmp2gale. If the input file contains an alpha layer, a mask bitmap will be generated. Output files will be named .bmp and -m.bmp. Options: --version Show the version and exit. -f, --force Overwrite output file if it exists. --help Show this message and exit. ``` -------------------------------- ### lmgraph --help output Source: https://pylivemaker.readthedocs.io/en/latest/cli.html Shows the lmgraph command-line help, including usage, arguments, and options. Use this to understand how to generate a DOT graph from a LiveNovel script file. ```console $ lmgraph --help Usage: lmgraph [OPTIONS] LSB_FILE [OUT_FILE] Generate a DOT syntax graph for a LiveNovel game. lsb_file should be a path to the root script node - this should always be ゲームメイン.lsb (game_main.lsb) for LiveMaker games. If output file is not specified, it defaults to .dot The output graph will start with game_main as the root node and follow branches to all scenario scripts, which should give a general approximation of the original LiveMaker scenario chart. Options: --version Show the version and exit. --help Show this message and exit. ``` -------------------------------- ### Get command by line number Source: https://pylivemaker.readthedocs.io/en/latest/_modules/livemaker/lsb/lmscript.html Returns a tuple of (cmd_index, cmd) for the given line number. Raises KeyError if the line number does not exist. ```python def get_command(self, line_no): """Get specified command by line number. Returns: tuple(cmd_index, cmd) Raises: KeyError: the specified line_no does not exist in this LSB. """ index = self._cmd_index[line_no] return index, self.commands[index] ``` -------------------------------- ### Dump LSB files with lmlsb dump Source: https://pylivemaker.readthedocs.io/en/latest/_sources/usage.rst.txt Dumps LSB files to text for inspection. The example dumps gamemain.lsb and 00000001.lsb after changing into the game_files directory. ```shell $ cd game_files $ lmlsb dump ゲームメイン.lsb > gamemain.txt $ lmlsb dump 00000001.lsb > 00000001.lsb.txt ``` -------------------------------- ### make_menu Source: https://pylivemaker.readthedocs.io/en/latest/livemaker.lsb.html Factory function to create a selection menu instance from LSB commands. ```APIDOC ## livemaker.lsb.menu.make_menu ### Description Return a selection menu instance for menu starting at the specified command index. ### Function Signature `make_menu(lsb, index, **kwargs)` ### Parameters - **lsb** (LMScript) - Required - LSB script instance - **index** - Required - Command index - **kwargs** - Optional - Additional keyword arguments passed to the menu constructor ``` -------------------------------- ### wrap_prop context manager wrapper Source: https://pylivemaker.readthedocs.io/en/latest/_modules/funcy/objects.html Decorator factory that wraps property accessors (get, set, delete) with a context manager. The context manager is entered for each access. ```python def wrap_prop(ctx): """Wrap a property accessors with a context manager""" def decorator(prop): class WrapperProp(object): def __repr__(self): return repr(prop) def __get__(self, instance, type=None): if instance is None: return self with ctx: return prop.__get__(instance, type) if hasattr(prop, '__set__'): def __set__(self, name, value): with ctx: return prop.__set__(name, value) if hasattr(prop, '__del__'): def __del__(self, name): with ctx: return prop.__del__(name) return WrapperProp() return decorator ``` -------------------------------- ### lmar --help: list available commands Source: https://pylivemaker.readthedocs.io/en/latest/_sources/cli.rst.txt Shows the top-level help for the lmar CLI, listing its subcommands (l, strip, x) and global options. Use --help to discover available commands for any pylivemaker CLI tool. ```console $ lmar --help Usage: lmar [OPTIONS] COMMAND [ARGS]... Command-line tool for manipulating LiveMaker archives and EXEs. Options: --version Show the version and exit. --help Show this message and exit. Commands: l List the contents of the specified archive. strip Copy the specified LiveMaker EXE but remove the LiveMaker archive. x Extract the specified archive. ``` -------------------------------- ### get_text_blocks method - return text blocks Source: https://pylivemaker.readthedocs.io/en/latest/_modules/livemaker/lsb/lmscript.html Returns a list of (identifier, block) tuples for all text blocks in the script. Uses text_scenarios to get scenarios and creates TextBlockIdentifier for each block. ```python blocks = [] for line_no, name, scenario in self.text_scenarios(run_order=run_order): for i, block in enumerate(scenario.get_text_blocks()): id_ = TextBlockIdentifier(self.call_name, line_no, name=name, block_index=i) blocks.append((id_, block)) return blocks ``` -------------------------------- ### lmgraph --help: generate DOT graph Source: https://pylivemaker.readthedocs.io/en/latest/_sources/cli.rst.txt Shows usage for the lmgraph CLI, which generates a graphviz DOT syntax graph of branches between LiveNovel script files. The root script file should be game_main.lsb; output defaults to .dot. Branch condition labels may not be 100% accurate due to a naive implementation. ```console $ lmgraph --help Usage: lmgraph [OPTIONS] LSB_FILE [OUT_FILE] Generate a DOT syntax graph for a LiveNovel game. lsb_file should be a path to the root script node - this should always be ゲームメイン.lsb (game_main.lsb) for LiveMaker games. If output file is not specified, it defaults to .dot The output graph will start with game_main as the root node and follow branches to all scenario scripts, which should give a general approximation of the original LiveMaker scenario chart. Options: --version Show the version and exit. --help Show this message and exit. ``` -------------------------------- ### Parse LPM parameters with _parse_params Source: https://pylivemaker.readthedocs.io/en/latest/_modules/livemaker/lsb/menu.html Parses a list of parser parameters into a dictionary of configuration keys for a Live Preview menu. Each parameter is converted to a string or integer as indicated by comments, with keys like parent, menu_file, and selection_time. ```python @classmethod def _parse_params(cls, params): params = params.parsers return { "parent": str(params[0]), # parent menu "menu_file": str(params[1]), # source LPM file "in_time": int(str(params[2])), # fade-in time "out_time": int(str(params[3])), # fade-out duration "hover_sound": str(params[4]), # hover sound effect "select_sound": str(params[5]), # select sound effect "disable_rclick": int(str(params[6])), # disable right click "enabled_var": str(params[7]), # choice enabled array var "visible_var": str(params[8]), # choice visible array var "selection_time": int(str(params[9])), # time before selection expires (countdown timer) "selected_var": str(params[10]), # choice (pre-)selected var } ``` -------------------------------- ### Module header and imports for livemaker.lsb.novel Source: https://pylivemaker.readthedocs.io/en/latest/_modules/livemaker/lsb/novel.html The module starts with a license header and imports required libraries including enum, os, re, _markupbase, bisect, construct, loguru, lxml, and internal modules. ```python # -*- coding: utf-8 # # Copyright (C) 2019 Peter Rowlands # Copyright (C) 2014 tinfoil # # This file is a part of pylivemaker. # # This program is free software: you can redistribute it and/or modify it under # the terms of the GNU General Public License as published by the Free Software # Foundation, either version 3 of the License, or (at your option) any later # version. # # This program is distributed in the hope that it will be useful, but WITHOUT # ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS # FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. # # You should have received a copy of the GNU General Public License along with # this program. If not, see . """LiveMaker LiveNovel LNS script classes.""" import enum import os import re import _markupbase from bisect import bisect import construct from loguru import logger from lxml import etree from .core import BaseSerializable, LiveParser from ..exceptions import BadLnsError, InvalidCharError from .translate import BaseTranslatable ``` -------------------------------- ### Run pre-commit and tests Source: https://pylivemaker.readthedocs.io/en/latest/contributing.html Runs pre-commit checks on all files and executes the test suite using either setup.py test or pytest. ```bash $ pre-commit run --all-files $ python setup.py test or pytest ``` -------------------------------- ### Find archive offset Source: https://pylivemaker.readthedocs.io/en/latest/_modules/livemaker/archive.html Determines the offset where the LiveMaker archive starts. If the file begins with 'MZ', it is treated as an MS executable and the offset is read from the last 6 bytes; otherwise, the offset is 0. ```python def _find_archive_offset(self): """Find offset for the start of the archive.""" self.fp.seek(0) if self.fp.read(2) == b"MZ": # File is an MS executable self.is_exe = True self.fp.seek(-2, 2) # Check for 'lv' trailer if self.fp.read(2) != b"lv": raise BadLiveMakerArchive("EXE does not contain a LiveMaker archive.") # Read offset for start of archive self.fp.seek(-6, 2) (offset,) = struct.unpack("