memcard
Whole memory-card sync: an emulator's Slot-1 card as one owned image.
Whole memory-card sync: an emulator's Slot-1 card as one owned image.
Distinct from the archive path in saves.py, which ships only what a session changed. A card travels whole, so a user's card can be laid down on any pooled container and the previous player's saves never survive into the next session. The card is a directory (a folder card), which is what makes it zippable and replaceable as an image; a single-file card is refused rather than mangled.
attributelog= logging.getLogger(__name__)attributeLOCK= Lock()Serializes whole-card operations.
Staging and backup paths are derived from the card name alone, so two concurrent replaces would rmtree each other mid-write.
func_card_files(card) -> list[Path]List every regular file in the card directory, sorted, skipping symlinks.
paramcardPathThe folder card's directory.
Returns
listThe files found, in sorted order.
func_is_blank_marker(path, card, marker) -> boolWhether path is the marker file while it is still the empty one we laid down.
parampathPathA file inside the card.
paramcardPathThe folder card's directory.
parammarkerOptional[str]The marker filename the emulator expects, or None when it has none.
Returns
boolTrue only for the marker file while it is still zero bytes.
funcensure_card(card, marker) -> NoneHave a card the emulator will actually open waiting at card.
A bare directory is not enough. PCSX2 skips any directory in its memcards folder that carries no marker file, so the slot reads as missing and the game has nowhere to save. The marker goes down empty, which is exactly what PCSX2 writes when it creates a folder card, and stays empty until the card is formatted.
paramcardPathThe folder card's directory, created if missing.
parammarkerOptional[str]The marker filename to touch inside it, or None to skip the marker.
Returns
Nonefuncbuild_archive(card, marker=None) -> Optional[Union[bytes, str]]Zip the whole card at card, members relative to the card root.
Relative so the image carries no trace of the card's name and can be laid down on a container that calls its card something else. A card holding nothing but the blank marker counts as no card at all.
paramcardPathThe folder card's directory.
parammarkerOptional[str]= NoneThe marker filename the emulator expects, or None when it has none.
Returns
typing.OptionalThe zip bytes, None when the slot holds no card, or an error string when
funcreplace(card, content, marker=None) -> Union[int, str]Wipe the card at card and lay the pulled image down in its place.
The whole card is replaced with no per-file merge: that is what isolates the next player on a pooled container from the last one. Extraction goes to a staging directory that is swapped over the live card, so a failure part way through never leaves a half-wiped card.
paramcardPathThe folder card's directory to replace.
paramcontentbytesThe zip image of the card, members relative to the card root.
parammarkerOptional[str]= NoneThe marker filename to lay down before the members, or None to skip it.
Returns
typing.UnionThe number of files written, or an error string when the slot holds a