webstation-broker
DeveloperPython referenceemulators

emulators.wii_nand

Placement rules for a Wii NAND title save, shared by Dolphin and RetroArch's Dolphin core.

Placement rules for a Wii NAND title save, shared by Dolphin and RetroArch's Dolphin core.

Both keep the emulated NAND as an ordinary tree: title/<high>/<low>/data/... holds a title's save, and sys, ticket, a system title and a title's content are the console's own. Where the tree lives differs (Wii in Dolphin's user folder, saves/dolphin-emu/User/Wii under RetroArch), so the caller names it. The functions here take no emulator, so they stay pure.

attributeSAVE_SHAPE
= 'title/<00010000|00010001|00010004>/<title id>/data/...'

The save shape a save KindSpec advertises for a Wii session.

attributeNAND_EXPECTED
= f'a Wii save, {SAVE_SHAPE}'

What a Wii save member must look like, for refusals.

attributeNAND_TITLE_RE
= re.compile('title', re.ASCII)

The NAND folder every installed title's data sits under.

attributeNAND_HIGH_RE
= re.compile('0001000[014]', re.ASCII)

A title id's high half for a title with player saves: a disc, a channel, or a disc with a channel.

attributeNAND_LOW_RE
= re.compile('[0-9A-Fa-f]{8}', re.ASCII)

A title id's low half: the four-character game code, in hex.

funcunwrap(parts, wrappers) -> tuple[str, ...]

Strip the first wrapper a member path arrived under.

A wrapper is only stripped when something is left below it, so a file named like a wrapper folder is not emptied away.

parampartstuple[str, ...]

The member's components.

paramwrapperstuple[tuple[str, ...], ...]

Candidate leading folders, longest first.

Returns

tuple

The components below the wrapper, or parts when none matched.

funcis_nand_system(rest) -> bool

Tell whether a NAND path is system or install data rather than a title's save.

Such a path is placed as named, so the plan check refuses it against the emulator's protected globs as emulator configuration, which tells the player more than a layout refusal would.

paramresttuple[str, ...]

The path's components below the NAND root.

Returns

bool

True under sys or ticket, a system title (title/00000001), or a title's content.

funcnand_leaf_refusal(member, expected=NAND_EXPECTED) -> imports.ImportRefusal

Refuse a Wii member that is not under a title's data folder, naming what it looks like.

parammemberimports.ImportMember

The member.

paramexpectedstr
= NAND_EXPECTED

The accepted shape, in words.

Returns

webstation_broker.imports.ImportRefusal

A conversion refusal for an SD-card export, a source refusal for a

funcplace_nand(member, session, *, subtree, wrappers, expected=NAND_EXPECTED) -> Union[imports.Placement, imports.ImportRefusal]

Place a file of a Wii title's save under <subtree>/title/<high>/<low>/data.

The path is found below at most one wrapper. A title reads its save from the folder named for its own id, so the title is held strictly to the session's game. System and install data is placed as named, for the plan check to refuse as protected.

parammemberimports.ImportMember

The member.

paramsessionimports.SessionIdentity

The session's identity.

paramsubtreestr

Where the NAND tree lives, relative to the save root.

paramwrapperstuple[tuple[str, ...], ...]

The leading folders a NAND path may arrive under, longest first.

paramexpectedstr
= NAND_EXPECTED

The accepted shape, in words.

Returns

typing.Union

The placement, or a refusal.