EmuLibrary is a library extension for Playnite, an open source video game library manager, focused on emulator ROM management.
While Playnite has had built-in support for scanning paths for installed ROMs and adding them to the library since version 9, EmuLibrary provides alternate functionality.
EmuLibrary treats one or more folders of ROMs/Disc images as a library from which you can "install" games. It can be useful if you have a large collection of emulated games and limited storage where you play them versus where you store them (HTPC vs. NAS, for example). It also is useful for keeping the list of emulated games up to date, and for being able to filter via installed/uninstalled.
Disclaimer: I created this extension for my own usage, and that is still the primary focus. Because of this, many parts of it are still tailored to my personal needs and usage patterns. Despite that, I wanted to share it with others in case it is useful to them. It is still in the process of being (slowly) adapted for more general use.
To set it up, you create mappings to combine one of each of the following:
For source and destination, only valid Windows file paths are currently supported. The intended use case is for having the source be an SMB file share (either via UNC path or mapped drive), and the destination be a local path. However, any valid file path should work for either. This means that you can get creative with the source if you have a way to mount alternate remote storage at a Windows file path.
Additionally, for destination paths, relativity to the Playnite folder is preserved if you are using a portable installation of Playnite and your destination is below that folder hierarchically. This means that, for example, if your portable installation is at D:\playnite, and you choose D:\playnite\rominstall as your destination, it will be saved internally as {PlayniteDir}\rominstall.
SingleFile is the simplest type of ROM supported. This is for source folders in which each ROM is fully contained in a single file. It's commonly used for older, non-disc-based systems where the whole ROM consists of a single file. (Ex. .nes, .sfc, .md, etc.). Archive formats are supported as well if the emulator supports them directly. (Ex. .zip)
With the MultiFile type, each subfolder directly within the source folder is scanned as a potential "ROM". This is for games that have multiple loose files. (Ex. one or more .bin/.cue, with optional .m3u). When installing a MultiFile game, the whole folder is copied.
To determine which file is used as the one to tell the emulator to load, all files matching the configured emulator profile's supported extensions are considered. Precedence is by configured image extension list order, and then by alphabetical order. For example, if file names are the same except for (Disc 1) versus (Disc 2), the first disc takes precedence. Similarly, if you have .cue in the extension list before .m3u (as some of the built-in profiles have at the time of writing), .cue would be chosen over .m3u, which may not be desired for multi-disc games.
The Yuzu type supports Nintendo Switch emulators that share Yuzu's architecture: Yuzu, Eden, and Citron-Neo. Select which emulator to use via the dropdown in the mapping settings — this controls where the plugin looks for keys and the NAND directory.
To add a functional mapping, select the appropriate emulator in the dropdown, then set the Playnite emulator entry to match (it does not need to be a built-in listing; custom entries work fine). In the source path, loose XCI/NSP/XCZ/NSZ files in the root of the path are considered.
Unlike the SingleFile/MultiFile types, this type scans by its own fixed list of formats (XCI/NSP/XCZ/NSZ) rather than the emulator profile's configured image extensions, so the profile does not need any image extensions defined.
NSP/NSZ files can also be updates and DLC, rather than just games. Unlike with Tinfoil shares, files are not required to include the title id in the filename. Additionally, while destination path must point to a folder that exists, the setting is ignored. Games install into the NAND directory configured in the selected emulator profile.
When a game is installed, the latest update and any DLC from the source will also be installed to the emulator's NAND, in that order (Game, Update if available, each available DLC). Games already installed will be imported, whether or not they exist in the source folder, and will display as installed. As expected, uninstalling a game will remove the game from the NAND. (While these emulators do not support XCZ or NSZ files for launching or installing to NAND, this plugin installs directly to the NAND, without relying on the emulator's built-in install functionality)
Game names and other details are enriched from an online database where possible — see Metadata Enrichment.
The PS3 type adds support for PlayStation 3 games run under RPCS3. It has a beta level of quality of support. Select RPCS3 as the emulator for the mapping (built-in or custom).
Like the Yuzu type, this type scans by its own format logic (.iso/.pkg/.rap) rather than the emulator profile's configured image extensions, so the profile does not need any image extensions defined — RPCS3's built-in profile declares none, and that is fine.
Unlike the other types, a PS3 "game" is a composite: a base (either a disc image or a downloadable PKG game) plus any number of update PKGs, DLC PKGs, and RAP license files. The scanner treats each immediate subfolder of the source path as one title, and the recommended layout groups a title's content together:
<SourcePath>/
BLES01234 - Demon's Souls/
BLES01234 - Demon's Souls.iso # encrypted disc image
BLES01234 - Demon's Souls.dkey # disc key (matching basename — required by RPCS3)
updates/ <patch>.pkg ... # installed in APP_VER order (from each PKG, never the filename)
dlc/ <dlc>.pkg ...
licenses/ EP0001-BLES01234_00-DLC0001.rap # filename is the content-id
NPUB30001 - Some PSN Game/
NPUB30001 - Some PSN Game.pkg # PKG base game (no disc image)
updates/ ...
dlc/ ...
licenses/ ...
The updates/, dlc/, and licenses/ subfolders are optional and case-insensitive. The scanner is tolerant of looser layouts too — PKGs are classified by their own metadata (the PKG patch flag plus PARAM.SFO fields), so a PKG dropped anywhere under the title folder is still categorized correctly; the subfolder name is used as an additional hint.
Installing a title can touch two destinations:
.iso plus its matching .dkey, or a decrypted .iso/PS3_GAME folder) are copied to the mapping's destination path. The .dkey sidecar is copied alongside the image so RPCS3 can load the encrypted ISO directly — there is no decrypt-on-install step.dev_hdd0/game/<TITLE_ID> (under the selected emulator's install directory). Updates are applied in ascending APP_VER order. RAP licenses are copied into dev_hdd0/home/00000001/exdata.Both halves are handled in-process — RPCS3 is not invoked to install anything. Uninstalling removes the copied disc image/folder and/or the dev_hdd0/game/<TITLE_ID> directory; save data (which RPCS3 stores elsewhere) is left untouched.
Game names and other details are enriched from an online database where possible — see Metadata Enrichment.
The Wii U type adds support for Nintendo Wii U games run under Cemu. It has a beta level of quality of support. Select Cemu as the emulator for the mapping (built-in or custom).
Like the Yuzu and PS3 types, this type scans by its own format logic rather than the emulator profile's configured image extensions, so the profile does not need any image extensions defined. It recognizes every common Wii U source format found directly under the source path:
title.tmd, the encrypted .app contents, and a .tik ticket.code/, content/, and meta/ subfolders..wux (or .wud) with a sibling disc key named <image>.key (or game.key)..wua archives — Cemu's single-file compressed format.Decryption is done natively in-process (it does not shell out to other tools); the Wii U common key is read from keys.txt in the Cemu folder, and disc images additionally need their per-disc .key. The plugin never installs into Cemu's NAND — Cemu launches games directly from the installed file/folder.
Like PS3, a Wii U "game" is a composite: a base title plus its updates and DLC. Wii U updates are cumulative, so only the latest update is applied (along with any DLC); there are no separate license files. The install model is WUA-first:
.wua, a standalone disc image (.wux/.wud + .key), or a loadiine folder with no separate update/DLC — it is copied as-is to the mapping's destination path..wua at the destination, with the latest update and DLC merged in. Merging separate updates/DLC into a pre-existing .wua base is not supported.Each title installs into its own destination subfolder named <name> [<title id>], so installed state and identity are recovered from disk on each scan. Uninstalling removes that subfolder.
Game names come from each title's decrypted meta.xml, and other details are enriched from an online database where possible — see Metadata Enrichment.
The 3DS type adds support for Nintendo 3DS games run under Azahar (a Citra fork). It has a beta level of quality of support. Select Azahar as the emulator for the mapping (built-in or custom).
Like the other console types, this type scans by its own format logic rather than the emulator profile's configured image extensions, so the profile does not need any image extensions defined. It recognizes three source shapes found directly under the source path:
.3ds, .cci, .cxi, .3dsx, and their compressed Z3DS counterparts .zcci, .zcxi, .z3dsx. These must already be decrypted dumps (Azahar rejects encrypted images)..cia and .zcia files. Each is one title; base/update/DLC .cias are grouped by their shared base title id.tmd.<version> plus content files named by hex content id (the layout produced by CDN downloads). Base, update, and DLC folders are grouped by the base title id read from the tmd, not by the folder-name suffix.Like PS3 and Wii U, a 3DS "game" is a composite: a base title plus its updates and DLC. 3DS updates are cumulative, so only the latest update is applied (along with any DLC); there are no separate license files. Installing differs by source shape:
Decryption needs the universal retail 3DS AES keys. These are read from your own Azahar — primarily its built-in key blob, with an aes_keys.txt (in Azahar's sysdata folder, beside the source, or a 3DS Keys/ folder on the source) as a fallback — so the plugin embeds no keys and requires nothing you don't already need to run Azahar. If no keys can be found, content-store install (CIA/CDN) is refused with a clear message; loose-file copy is unaffected. A CDN folder additionally needs a ticket (.tik) for its title key — <folder>.tik beside the folder, or any .tik/cetk inside it — and refuses install with a message if none is present (CIAs carry their own ticket).
Installed state is derived from Azahar's SD store (for content-store titles) or the destination folder (for loose copies) on each scan. Uninstalling removes the installed SD title directories or the copied file.
Note: this targets the default Azahar that is not linked to a real console. If you have linked a console (Azahar wraps installed content in console-unique encryption in that case), use Azahar's own GUI installer instead.
Game icons come from each title's embedded SMDH where readable, and other details are enriched from an online database where possible — see Metadata Enrichment. By default the game name is the normalized filename (overridden by the 3dsdb full name when a title-id match exists), because the SMDH's embedded title is often shortened for the handheld's home menu; enable Prefer in-file (SMDH) title over filename on the mapping to use the embedded title instead.
The Xbox 360 type adds support for Xbox 360 games run under Xenia (Canary or master — the content layout is the same across forks). It has a beta level of quality of support. Select Xenia as the emulator for the mapping (built-in or custom).
Like the other console types, this type scans by its own format logic rather than the emulator profile's configured image extensions, so the profile does not need any image extensions defined. It is entirely keyless — there is no decryption or extraction step; every install is a plain file copy. It recognizes these source shapes found directly under the source path:
.iso (XGD / XDVDFS). Redump .7z dumps are presumed already extracted to .iso.LIVE) for XBLA, Games on Demand, and standalone apps. Zipped digital dumps are presumed already unzipped (the internal <TitleID>/<ContentType>/<ContentID> folder layout is what is scanned).TU_* STFS packages (these shares are foldered by media id).Like PS3 and Wii U, an Xbox 360 "game" is a composite: a base (a disc image or a digital package) plus its updates and DLC. Updates are cumulative, so only the latest update is applied (along with any DLC); there are no separate license files.
The plugin reads each base's title id and media id to group content — from the disc's default.xex for ISOs, or from the STFS header for digital packages. Title updates are matched to a base by media id (a disc release and a Games-on-Demand release of the same game share a title id but differ by media id, and an update only applies to the matching one); DLC is matched by title id. STFS content type alone does not separate a standalone app from a DLC add-on (both can sit under 00000002), so the plugin probes whether the package contains a default.xex to tell them apart.
Installing differs by piece:
.iso or the digital container) is copied to the mapping's destination path and launched directly — Xenia opens it in place.content/ beside xenia.exe if a portable.txt is present there, otherwise %USERPROFILE%\Documents\Xenia\content. Xenia applies them automatically at boot by title id + media id. If the content folder can't be resolved, base install still works but update/DLC install is refused with a clear message.Installed state is derived from disk on each scan (the base copy in the destination plus each update/DLC file in the content tree). Uninstalling removes the copied base and the specific update/DLC files that were written — it does not delete the whole title content directory, so save data (stored under the same title id) is left untouched.
Note: each disc of a multi-disc set is treated as its own game. Some demo/promo discs are plain DVD images with no Xbox game partition; these can't be identified and are skipped with a warning.
Game names and thumbnails come from each digital package's embedded STFS metadata where available; disc titles fall back to the title-id database or the No-Intro filename. See Metadata Enrichment.
The PSP type adds support for PlayStation Portable games run under PPSSPP — either the standalone emulator or the PPSSPP libretro core in RetroArch. It has a beta level of quality of support. Select PPSSPP (or RetroArch) as the emulator for the mapping (built-in or custom).
Like the other console types, this type scans by its own format logic rather than the emulator profile's configured image extensions, so the profile does not need any image extensions defined. The source is a flat directory of disc images, freely named, in any of these formats:
.iso — a raw UMD image (ISO9660)..chd — MAME/chdman compressed image (v5; zstd/zlib/lzma hunks). It is read directly — during a scan only the few sectors needed to identify the title are decompressed, not the whole image..cso / .zso — CISO/ZISO block-compressed images..pbp — an EBOOT.PBP (PSN / minis / homebrew).Beside the images sit optional update/DLC payload folders, each named by the bare 9-character title id (e.g. ULUS10538). The scanner reads the DISC_ID out of each image (cached) and pairs the sibling folder of that name as the title's update/DLC content — association is by the id inside the image, not by filename, so nothing needs renaming.
Installing a title touches two destinations:
.chd/.cso/.pbp natively, so there is no decompression on install).PSP/GAME/<title id>, where PPSSPP applies it at launch. Multiple updates are applied in ascending APP_VER order (read from each payload's PBOOT.PBP, never the folder name). There are no separate license files — PSP DRM (EDAT) is keyed to the console and is PPSSPP's job; the plugin only copies.The memory-stick root is resolved from the selected emulator profile: for standalone PPSSPP a portable memstick/ beside the exe, else memstick_dir.txt, else Documents/PPSSPP; for the RetroArch core it is <system_directory>/PPSSPP. A base-only title installs regardless, but if a title has update/DLC content and the memory stick can't be resolved, that install is refused with a clear message.
Installed state is derived from disk on each scan (the base copy in the destination plus each payload folder under the memory stick). Uninstalling removes the copied base image and the PSP/GAME/<title id> payload directories it wrote; save data (PSP/SAVEDATA) is left untouched.
Game icons come from each image's embedded ICON0.PNG — read from /PSP_GAME/ICON0.PNG on a UMD image (.iso/.chd/.cso/.zso) or from the icon segment of a .pbp. Game names come from the image's PARAM.SFO title, falling back to the normalized filename. There is no external metadata provider for PSP.
Note: multi-disc PSP games are out of scope.
The PS Vita type adds support for PlayStation Vita games run under Vita3K. It has a beta level of quality of support. Select Vita3K as the emulator for the mapping.
Launching requires a custom Vita3K emulator profile. Vita3K runs an already-installed title by its title id (Vita3K.exe -r <TITLE_ID>), not by a file path — so Playnite's built-in Vita3K profile (which passes the ROM path as "{ImagePath}") does not work: Vita3K treats the path as content to install and reports "is not a supported content type." Because this plugin installs each base into ux0/app/<TITLE_ID> (so the game's install-directory name is the title id), add a custom Vita3K emulator profile in Playnite with:
Vita3K.exe-r "{InstallDirName}"Playnite expands {InstallDirName} to the install-directory name (the title id), producing -r PCSE01056 — the correct "run installed title" command. This one profile works for every Vita game the plugin installs; no per-game editing. Select this custom profile (not the built-in one) for the mapping.
Like the other console types, this type scans by its own format logic rather than the emulator profile's configured image extensions, so the profile does not need any image extensions defined.
Two source formats are supported:
app/<TITLE_ID>/ tree (which carries its sce_sys/package/work.bin license inside) and a game update is a patch/<TITLE_ID>/ tree. No decryption is done — the plugin only copies..pkg distribution (a NoIntro-style folder per item, each holding a .pkg and, for base games and DLC, a work.bin). Base games, game updates, DLC, and their licenses are decrypted and extracted on install. The AES/PKG and work.bin/zRIF handling is built in (no external tool required); the fixed pkg_vita keys are public constants.In both cases the scanner pairs a base with its updates/DLC by title id (the folder name for NoNpDrm, the package content id for PSN), so nothing needs renaming.
Installing places content into Vita3K's ux0: the base into ux0/app/<TITLE_ID>, each update into ux0/patch/<TITLE_ID>, and (PSN) DLC into ux0/addcont/<TITLE_ID>/<CONTENT_ID>, where Vita3K applies them at launch. Multiple updates are applied in ascending APP_VER order (read from each update's param.sfo, never the folder name). For NoNpDrm the work.bin license travels inside the app tree; for PSN the license is written to ux0/license/<TITLE_ID>/<CONTENT_ID>.rif (the flattened path Vita3K reads, with no app subfolder), which Vita3K uses to decrypt the retail eboot at launch.
The ux0 root is resolved from the selected Vita3K emulator (its pref-path). Installed state is derived from disk on each scan (ux0/app/<TITLE_ID> present). Uninstalling removes the app/<TITLE_ID>, patch/<TITLE_ID>, addcont/<TITLE_ID>, and license/<TITLE_ID> entries it wrote; save data (ux0/user) is left untouched.
Game icons come from each title's sce_sys/icon0.png — a loose file for NoNpDrm, or extracted from the base package for PSN; game names come from the title's param.sfo, falling back to the normalized folder name. There is no external metadata provider for PS Vita.
For some RomTypes, EmuLibrary looks up game details from a community metadata database and uses them in preference to whatever it can read out of the game files themselves. This generally yields cleaner, properly-formatted game names plus extra details that aren't present in the files at all.
| RomType | Provider | Matched by |
|---|---|---|
| Yuzu (Switch) | titledb | Title ID |
| PS3 | GameTDB | Disc serial (e.g. BLES01234) |
| Wii U | GameTDB | 6-char game code (e.g. AVEE0W), built from meta.xml |
| 3DS | 3dsdb | Title ID |
| Xbox 360 | x360db | Title ID |
When a match is found, these fields are filled in (shadowing anything derived from the files): name, description, developer, publisher, genres, and release date. Anything the provider doesn't supply falls back to what was read from the files, so you never end up worse off than without enrichment.
A few notes:
ExtensionsData\41e49490-0583-4148-94d2-940c7c74f1d9\metadata, and only re-downloaded when the cached copy is more than a day old. If a provider can't be reached, the most recent cached copy is used, and if there's no cached copy at all, enrichment is simply skipped — it never blocks or fails a library scan.meta.xml (Wii U files embed it), and GameTDB is only used for the extra fields. GameTDB's Wii U coverage is thin for eShop-only/indie titles, so many Wii U games are enriched by name alone.To get help, check out the #extension-support channel on the Playnite Discord, linked at the top of https://playnite.link/
The following files are generally useful for troubleshooting, relative to the folder where Playnite data is stored. For a portable installation, this is the same folder that Playnite is installed to. For non-portable installations, it is in AppData.
C#
100.0%
EmuLibrary is a library extension for Playnite, an open source video game library manager, focused on emulator ROM management.
While Playnite has had built-in support for scanning paths for installed ROMs and adding them to the library since version 9, EmuLibrary provides alternate functionality.
EmuLibrary treats one or more folders of ROMs/Disc images as a library from which you can "install" games. It can be useful if you have a large collection of emulated games and limited storage where you play them versus where you store them (HTPC vs. NAS, for example). It also is useful for keeping the list of emulated games up to date, and for being able to filter via installed/uninstalled.
Disclaimer: I created this extension for my own usage, and that is still the primary focus. Because of this, many parts of it are still tailored to my personal needs and usage patterns. Despite that, I wanted to share it with others in case it is useful to them. It is still in the process of being (slowly) adapted for more general use.
To set it up, you create mappings to combine one of each of the following:
For source and destination, only valid Windows file paths are currently supported. The intended use case is for having the source be an SMB file share (either via UNC path or mapped drive), and the destination be a local path. However, any valid file path should work for either. This means that you can get creative with the source if you have a way to mount alternate remote storage at a Windows file path.
Additionally, for destination paths, relativity to the Playnite folder is preserved if you are using a portable installation of Playnite and your destination is below that folder hierarchically. This means that, for example, if your portable installation is at D:\playnite, and you choose D:\playnite\rominstall as your destination, it will be saved internally as {PlayniteDir}\rominstall.
SingleFile is the simplest type of ROM supported. This is for source folders in which each ROM is fully contained in a single file. It's commonly used for older, non-disc-based systems where the whole ROM consists of a single file. (Ex. .nes, .sfc, .md, etc.). Archive formats are supported as well if the emulator supports them directly. (Ex. .zip)
With the MultiFile type, each subfolder directly within the source folder is scanned as a potential "ROM". This is for games that have multiple loose files. (Ex. one or more .bin/.cue, with optional .m3u). When installing a MultiFile game, the whole folder is copied.
To determine which file is used as the one to tell the emulator to load, all files matching the configured emulator profile's supported extensions are considered. Precedence is by configured image extension list order, and then by alphabetical order. For example, if file names are the same except for (Disc 1) versus (Disc 2), the first disc takes precedence. Similarly, if you have .cue in the extension list before .m3u (as some of the built-in profiles have at the time of writing), .cue would be chosen over .m3u, which may not be desired for multi-disc games.
The Yuzu type supports Nintendo Switch emulators that share Yuzu's architecture: Yuzu, Eden, and Citron-Neo. Select which emulator to use via the dropdown in the mapping settings — this controls where the plugin looks for keys and the NAND directory.
To add a functional mapping, select the appropriate emulator in the dropdown, then set the Playnite emulator entry to match (it does not need to be a built-in listing; custom entries work fine). In the source path, loose XCI/NSP/XCZ/NSZ files in the root of the path are considered.
Unlike the SingleFile/MultiFile types, this type scans by its own fixed list of formats (XCI/NSP/XCZ/NSZ) rather than the emulator profile's configured image extensions, so the profile does not need any image extensions defined.
NSP/NSZ files can also be updates and DLC, rather than just games. Unlike with Tinfoil shares, files are not required to include the title id in the filename. Additionally, while destination path must point to a folder that exists, the setting is ignored. Games install into the NAND directory configured in the selected emulator profile.
When a game is installed, the latest update and any DLC from the source will also be installed to the emulator's NAND, in that order (Game, Update if available, each available DLC). Games already installed will be imported, whether or not they exist in the source folder, and will display as installed. As expected, uninstalling a game will remove the game from the NAND. (While these emulators do not support XCZ or NSZ files for launching or installing to NAND, this plugin installs directly to the NAND, without relying on the emulator's built-in install functionality)
Game names and other details are enriched from an online database where possible — see Metadata Enrichment.
The PS3 type adds support for PlayStation 3 games run under RPCS3. It has a beta level of quality of support. Select RPCS3 as the emulator for the mapping (built-in or custom).
Like the Yuzu type, this type scans by its own format logic (.iso/.pkg/.rap) rather than the emulator profile's configured image extensions, so the profile does not need any image extensions defined — RPCS3's built-in profile declares none, and that is fine.
Unlike the other types, a PS3 "game" is a composite: a base (either a disc image or a downloadable PKG game) plus any number of update PKGs, DLC PKGs, and RAP license files. The scanner treats each immediate subfolder of the source path as one title, and the recommended layout groups a title's content together:
<SourcePath>/
BLES01234 - Demon's Souls/
BLES01234 - Demon's Souls.iso # encrypted disc image
BLES01234 - Demon's Souls.dkey # disc key (matching basename — required by RPCS3)
updates/ <patch>.pkg ... # installed in APP_VER order (from each PKG, never the filename)
dlc/ <dlc>.pkg ...
licenses/ EP0001-BLES01234_00-DLC0001.rap # filename is the content-id
NPUB30001 - Some PSN Game/
NPUB30001 - Some PSN Game.pkg # PKG base game (no disc image)
updates/ ...
dlc/ ...
licenses/ ...
The updates/, dlc/, and licenses/ subfolders are optional and case-insensitive. The scanner is tolerant of looser layouts too — PKGs are classified by their own metadata (the PKG patch flag plus PARAM.SFO fields), so a PKG dropped anywhere under the title folder is still categorized correctly; the subfolder name is used as an additional hint.
Installing a title can touch two destinations:
.iso plus its matching .dkey, or a decrypted .iso/PS3_GAME folder) are copied to the mapping's destination path. The .dkey sidecar is copied alongside the image so RPCS3 can load the encrypted ISO directly — there is no decrypt-on-install step.dev_hdd0/game/<TITLE_ID> (under the selected emulator's install directory). Updates are applied in ascending APP_VER order. RAP licenses are copied into dev_hdd0/home/00000001/exdata.Both halves are handled in-process — RPCS3 is not invoked to install anything. Uninstalling removes the copied disc image/folder and/or the dev_hdd0/game/<TITLE_ID> directory; save data (which RPCS3 stores elsewhere) is left untouched.
Game names and other details are enriched from an online database where possible — see Metadata Enrichment.
The Wii U type adds support for Nintendo Wii U games run under Cemu. It has a beta level of quality of support. Select Cemu as the emulator for the mapping (built-in or custom).
Like the Yuzu and PS3 types, this type scans by its own format logic rather than the emulator profile's configured image extensions, so the profile does not need any image extensions defined. It recognizes every common Wii U source format found directly under the source path:
title.tmd, the encrypted .app contents, and a .tik ticket.code/, content/, and meta/ subfolders..wux (or .wud) with a sibling disc key named <image>.key (or game.key)..wua archives — Cemu's single-file compressed format.Decryption is done natively in-process (it does not shell out to other tools); the Wii U common key is read from keys.txt in the Cemu folder, and disc images additionally need their per-disc .key. The plugin never installs into Cemu's NAND — Cemu launches games directly from the installed file/folder.
Like PS3, a Wii U "game" is a composite: a base title plus its updates and DLC. Wii U updates are cumulative, so only the latest update is applied (along with any DLC); there are no separate license files. The install model is WUA-first:
.wua, a standalone disc image (.wux/.wud + .key), or a loadiine folder with no separate update/DLC — it is copied as-is to the mapping's destination path..wua at the destination, with the latest update and DLC merged in. Merging separate updates/DLC into a pre-existing .wua base is not supported.Each title installs into its own destination subfolder named <name> [<title id>], so installed state and identity are recovered from disk on each scan. Uninstalling removes that subfolder.
Game names come from each title's decrypted meta.xml, and other details are enriched from an online database where possible — see Metadata Enrichment.
The 3DS type adds support for Nintendo 3DS games run under Azahar (a Citra fork). It has a beta level of quality of support. Select Azahar as the emulator for the mapping (built-in or custom).
Like the other console types, this type scans by its own format logic rather than the emulator profile's configured image extensions, so the profile does not need any image extensions defined. It recognizes three source shapes found directly under the source path:
.3ds, .cci, .cxi, .3dsx, and their compressed Z3DS counterparts .zcci, .zcxi, .z3dsx. These must already be decrypted dumps (Azahar rejects encrypted images)..cia and .zcia files. Each is one title; base/update/DLC .cias are grouped by their shared base title id.tmd.<version> plus content files named by hex content id (the layout produced by CDN downloads). Base, update, and DLC folders are grouped by the base title id read from the tmd, not by the folder-name suffix.Like PS3 and Wii U, a 3DS "game" is a composite: a base title plus its updates and DLC. 3DS updates are cumulative, so only the latest update is applied (along with any DLC); there are no separate license files. Installing differs by source shape:
Decryption needs the universal retail 3DS AES keys. These are read from your own Azahar — primarily its built-in key blob, with an aes_keys.txt (in Azahar's sysdata folder, beside the source, or a 3DS Keys/ folder on the source) as a fallback — so the plugin embeds no keys and requires nothing you don't already need to run Azahar. If no keys can be found, content-store install (CIA/CDN) is refused with a clear message; loose-file copy is unaffected. A CDN folder additionally needs a ticket (.tik) for its title key — <folder>.tik beside the folder, or any .tik/cetk inside it — and refuses install with a message if none is present (CIAs carry their own ticket).
Installed state is derived from Azahar's SD store (for content-store titles) or the destination folder (for loose copies) on each scan. Uninstalling removes the installed SD title directories or the copied file.
Note: this targets the default Azahar that is not linked to a real console. If you have linked a console (Azahar wraps installed content in console-unique encryption in that case), use Azahar's own GUI installer instead.
Game icons come from each title's embedded SMDH where readable, and other details are enriched from an online database where possible — see Metadata Enrichment. By default the game name is the normalized filename (overridden by the 3dsdb full name when a title-id match exists), because the SMDH's embedded title is often shortened for the handheld's home menu; enable Prefer in-file (SMDH) title over filename on the mapping to use the embedded title instead.
The Xbox 360 type adds support for Xbox 360 games run under Xenia (Canary or master — the content layout is the same across forks). It has a beta level of quality of support. Select Xenia as the emulator for the mapping (built-in or custom).
Like the other console types, this type scans by its own format logic rather than the emulator profile's configured image extensions, so the profile does not need any image extensions defined. It is entirely keyless — there is no decryption or extraction step; every install is a plain file copy. It recognizes these source shapes found directly under the source path:
.iso (XGD / XDVDFS). Redump .7z dumps are presumed already extracted to .iso.LIVE) for XBLA, Games on Demand, and standalone apps. Zipped digital dumps are presumed already unzipped (the internal <TitleID>/<ContentType>/<ContentID> folder layout is what is scanned).TU_* STFS packages (these shares are foldered by media id).Like PS3 and Wii U, an Xbox 360 "game" is a composite: a base (a disc image or a digital package) plus its updates and DLC. Updates are cumulative, so only the latest update is applied (along with any DLC); there are no separate license files.
The plugin reads each base's title id and media id to group content — from the disc's default.xex for ISOs, or from the STFS header for digital packages. Title updates are matched to a base by media id (a disc release and a Games-on-Demand release of the same game share a title id but differ by media id, and an update only applies to the matching one); DLC is matched by title id. STFS content type alone does not separate a standalone app from a DLC add-on (both can sit under 00000002), so the plugin probes whether the package contains a default.xex to tell them apart.
Installing differs by piece:
.iso or the digital container) is copied to the mapping's destination path and launched directly — Xenia opens it in place.content/ beside xenia.exe if a portable.txt is present there, otherwise %USERPROFILE%\Documents\Xenia\content. Xenia applies them automatically at boot by title id + media id. If the content folder can't be resolved, base install still works but update/DLC install is refused with a clear message.Installed state is derived from disk on each scan (the base copy in the destination plus each update/DLC file in the content tree). Uninstalling removes the copied base and the specific update/DLC files that were written — it does not delete the whole title content directory, so save data (stored under the same title id) is left untouched.
Note: each disc of a multi-disc set is treated as its own game. Some demo/promo discs are plain DVD images with no Xbox game partition; these can't be identified and are skipped with a warning.
Game names and thumbnails come from each digital package's embedded STFS metadata where available; disc titles fall back to the title-id database or the No-Intro filename. See Metadata Enrichment.
The PSP type adds support for PlayStation Portable games run under PPSSPP — either the standalone emulator or the PPSSPP libretro core in RetroArch. It has a beta level of quality of support. Select PPSSPP (or RetroArch) as the emulator for the mapping (built-in or custom).
Like the other console types, this type scans by its own format logic rather than the emulator profile's configured image extensions, so the profile does not need any image extensions defined. The source is a flat directory of disc images, freely named, in any of these formats:
.iso — a raw UMD image (ISO9660)..chd — MAME/chdman compressed image (v5; zstd/zlib/lzma hunks). It is read directly — during a scan only the few sectors needed to identify the title are decompressed, not the whole image..cso / .zso — CISO/ZISO block-compressed images..pbp — an EBOOT.PBP (PSN / minis / homebrew).Beside the images sit optional update/DLC payload folders, each named by the bare 9-character title id (e.g. ULUS10538). The scanner reads the DISC_ID out of each image (cached) and pairs the sibling folder of that name as the title's update/DLC content — association is by the id inside the image, not by filename, so nothing needs renaming.
Installing a title touches two destinations:
.chd/.cso/.pbp natively, so there is no decompression on install).PSP/GAME/<title id>, where PPSSPP applies it at launch. Multiple updates are applied in ascending APP_VER order (read from each payload's PBOOT.PBP, never the folder name). There are no separate license files — PSP DRM (EDAT) is keyed to the console and is PPSSPP's job; the plugin only copies.The memory-stick root is resolved from the selected emulator profile: for standalone PPSSPP a portable memstick/ beside the exe, else memstick_dir.txt, else Documents/PPSSPP; for the RetroArch core it is <system_directory>/PPSSPP. A base-only title installs regardless, but if a title has update/DLC content and the memory stick can't be resolved, that install is refused with a clear message.
Installed state is derived from disk on each scan (the base copy in the destination plus each payload folder under the memory stick). Uninstalling removes the copied base image and the PSP/GAME/<title id> payload directories it wrote; save data (PSP/SAVEDATA) is left untouched.
Game icons come from each image's embedded ICON0.PNG — read from /PSP_GAME/ICON0.PNG on a UMD image (.iso/.chd/.cso/.zso) or from the icon segment of a .pbp. Game names come from the image's PARAM.SFO title, falling back to the normalized filename. There is no external metadata provider for PSP.
Note: multi-disc PSP games are out of scope.
The PS Vita type adds support for PlayStation Vita games run under Vita3K. It has a beta level of quality of support. Select Vita3K as the emulator for the mapping.
Launching requires a custom Vita3K emulator profile. Vita3K runs an already-installed title by its title id (Vita3K.exe -r <TITLE_ID>), not by a file path — so Playnite's built-in Vita3K profile (which passes the ROM path as "{ImagePath}") does not work: Vita3K treats the path as content to install and reports "is not a supported content type." Because this plugin installs each base into ux0/app/<TITLE_ID> (so the game's install-directory name is the title id), add a custom Vita3K emulator profile in Playnite with:
Vita3K.exe-r "{InstallDirName}"Playnite expands {InstallDirName} to the install-directory name (the title id), producing -r PCSE01056 — the correct "run installed title" command. This one profile works for every Vita game the plugin installs; no per-game editing. Select this custom profile (not the built-in one) for the mapping.
Like the other console types, this type scans by its own format logic rather than the emulator profile's configured image extensions, so the profile does not need any image extensions defined.
Two source formats are supported:
app/<TITLE_ID>/ tree (which carries its sce_sys/package/work.bin license inside) and a game update is a patch/<TITLE_ID>/ tree. No decryption is done — the plugin only copies..pkg distribution (a NoIntro-style folder per item, each holding a .pkg and, for base games and DLC, a work.bin). Base games, game updates, DLC, and their licenses are decrypted and extracted on install. The AES/PKG and work.bin/zRIF handling is built in (no external tool required); the fixed pkg_vita keys are public constants.In both cases the scanner pairs a base with its updates/DLC by title id (the folder name for NoNpDrm, the package content id for PSN), so nothing needs renaming.
Installing places content into Vita3K's ux0: the base into ux0/app/<TITLE_ID>, each update into ux0/patch/<TITLE_ID>, and (PSN) DLC into ux0/addcont/<TITLE_ID>/<CONTENT_ID>, where Vita3K applies them at launch. Multiple updates are applied in ascending APP_VER order (read from each update's param.sfo, never the folder name). For NoNpDrm the work.bin license travels inside the app tree; for PSN the license is written to ux0/license/<TITLE_ID>/<CONTENT_ID>.rif (the flattened path Vita3K reads, with no app subfolder), which Vita3K uses to decrypt the retail eboot at launch.
The ux0 root is resolved from the selected Vita3K emulator (its pref-path). Installed state is derived from disk on each scan (ux0/app/<TITLE_ID> present). Uninstalling removes the app/<TITLE_ID>, patch/<TITLE_ID>, addcont/<TITLE_ID>, and license/<TITLE_ID> entries it wrote; save data (ux0/user) is left untouched.
Game icons come from each title's sce_sys/icon0.png — a loose file for NoNpDrm, or extracted from the base package for PSN; game names come from the title's param.sfo, falling back to the normalized folder name. There is no external metadata provider for PS Vita.
For some RomTypes, EmuLibrary looks up game details from a community metadata database and uses them in preference to whatever it can read out of the game files themselves. This generally yields cleaner, properly-formatted game names plus extra details that aren't present in the files at all.
| RomType | Provider | Matched by |
|---|---|---|
| Yuzu (Switch) | titledb | Title ID |
| PS3 | GameTDB | Disc serial (e.g. BLES01234) |
| Wii U | GameTDB | 6-char game code (e.g. AVEE0W), built from meta.xml |
| 3DS | 3dsdb | Title ID |
| Xbox 360 | x360db | Title ID |
When a match is found, these fields are filled in (shadowing anything derived from the files): name, description, developer, publisher, genres, and release date. Anything the provider doesn't supply falls back to what was read from the files, so you never end up worse off than without enrichment.
A few notes:
ExtensionsData\41e49490-0583-4148-94d2-940c7c74f1d9\metadata, and only re-downloaded when the cached copy is more than a day old. If a provider can't be reached, the most recent cached copy is used, and if there's no cached copy at all, enrichment is simply skipped — it never blocks or fails a library scan.meta.xml (Wii U files embed it), and GameTDB is only used for the extra fields. GameTDB's Wii U coverage is thin for eShop-only/indie titles, so many Wii U games are enriched by name alone.To get help, check out the #extension-support channel on the Playnite Discord, linked at the top of https://playnite.link/
The following files are generally useful for troubleshooting, relative to the folder where Playnite data is stored. For a portable installation, this is the same folder that Playnite is installed to. For non-portable installations, it is in AppData.
C#
100.0%