webstation-broker
DeveloperPython referenceemulatorsemulators.azahar

emulators.azahar.Azahar

Nintendo 3DS via Azahar, driven by command line flags and config file patching.

Nintendo 3DS via Azahar, driven by command line flags and config file patching.

Azahar has no control API reachable from outside the process, so the broker pins qt-config.ini before every launch (no close confirmation, no update check, no Discord presence) and boots windowed with -w: fullscreen Azahar stops rendering when the display resizes under it, which happens whenever the player resizes their browser. Azahar installs no SIGTERM handler, so the stop is a hard kill and the dump takes whatever the game had already committed to disk.

There are no reachable save states: persistence is the game's own save data under the emulated SD card and NAND, and the archive is scoped to those save trees. At exit every file in the title save dirs written during the session gets its mtime refreshed so the delta dump ships those saves whole while other titles' saves stay filtered out. A resume slot is logged and ignored.

Attributes

attributename
= 'azahar'

Provider key, azahar.

attributedisplay_name
= 'Azahar'

Human-readable name.

attributesave_root
= USER_DIR

The data root the save subtrees hang off.

attributesave_subtrees
= (f'sdmc/Nintendo 3DS/{SYSTEM_ID}/{SDCARD_ID}/title', f'sdmc/Nintendo 3DS/{SYSTEM_ID}/{SDCARD_ID}/extdata', f'nand/data/{SYSTEM_ID}/extdata', f'nand/data/{SYSTEM_ID}/sysdata')

The SD title and extdata trees plus the NAND extdata and sysdata trees.

attributerom_extensions
= ROM_EXTENSIONS

Bootable formats, best first.

attributelog_path
= AZAHAR_LOG_PATH

The emulator log file.

attributeterm_timeout
= float(os.environ.get('AZAHAR_STOP_WAIT', '5'))

SIGTERM grace before SIGKILL (env AZAHAR_STOP_WAIT, default 5).

attribute_session_start
= 0.0

Functions

func__init__(self) -> None

Initialise the process handle and a zero session baseline.

paramself

Returns

None
funcprepare_restore(self) -> None

Stop a running Azahar so the archive can be extracted under it.

paramself

Returns

None
funcresolve_rom_file(self, path) -> Optional[Path]

The file Azahar should boot for path.

paramself
parampathPath

A ROM file, or a folder searched up to two levels deep.

Returns

typing.Optional

The file itself, the best-ranked bootable file in the folder, or None.

funclaunch(self, rom_path, resume_slot) -> None

Patch qt-config.ini and boot the game windowed.

paramself
paramrom_pathPath

The file to boot.

paramresume_slotOptional[int]

Ignored with a log line; there are no reachable save states.

Returns

None
func_modified_title_saves(self) -> list[Path]

Title save dirs holding a file written while the session ran.

paramself

Returns

list

The <titleHigh>/<titleLow> directories under every save group

funcsave_and_exit(self, slot) -> dict[str, Any]

Stop Azahar and mark this session's title saves for the dump.

paramself
paramslotint

Ignored; there are no save states.

Returns

dict

state_saved, state_slot and state_file, all None.

On this page