Node.js library for decoding and encoding Final Fantasy Pixel Remaster save files from Nintendo Switch, PC and PlayStation.
- All six games: Final Fantasy I–VI.
- Saves from Nintendo Switch, PC and PlayStation through one API.
- Save slots, bestiary and game settings.
- Nested JSON strings are unpacked into a plain object tree and packed back.
- TypeScript types for the save structure: characters, jobs, abilities, items, party, map, story flags and more.
- Works with files or with buffers.
- Two runtime dependencies, no native addons.
Saves can also be edited in the browser with an editor built on this library. Files are decoded locally and are not uploaded.
import { load, save } from 'ffpr';
const data = await load('path/to/save', 'pc');
data.userData.owendGil = 9999999;
await save('path/to/save', data, 'pc');All functions are async. type is the platform:
'switch', 'pc' or 'playstation',
'switch' by default.
load(filename, type?)reads and decodes a save file.save(filename, data, type?)encodes data and writes it to a file.unpack(buffer, type?)decodes file contents from aBufferor aUint8Array.pack(data, type?)encodes data into aBuffer.
load and unpack throw an error if the file is not a save of the given platform.
All functions and types of save data are described in the API reference.
npm i ffpror
pnpm add ffpror
yarn add ffpror
bun add ffprA save file is JSON in which nested objects are stored as JSON strings, several levels deep.
load and unpack parse them all into a single object tree,
save and pack encode them back.
pictureData is decoded from base64 into a Buffer.
Key names are exactly as the game writes them, including the developers' typos:
owendGil, importantOwendItemList, owendCrystalFlags, ownedKeyWaordList,
numberOfButtles, resolutionHight and others.
These are not mistakes in the library, do not "fix" them:
the game will not recognize renamed keys.
The structure is described by TypeScript types:
Master (save slot), Bestiary and Config (settings).
load returns their union, so cast the result:
import { load } from 'ffpr';
import type { Master } from 'ffpr';
const data = (await load('path/to/save', 'pc')) as Master;- Switch: JSON compressed with raw deflate and encrypted with Rijndael-256-CBC.
- PC: the same, encoded in base64.
- PlayStation: plain JSON.
If something doesnt work, or you just wanna talk to the creator or his mom, write @arelive. There also accepted kicks from volunteer project managers.