A save editor in the spirit of saveeditonline.com, but it actually understands the game. Instead of showing raw ID numbers, it maps everything to real names using the game's own data files, so you can edit a character's skills, abilities, afflictions, lost limbs, stats, and equipment directly.
Tested games — a real save has been opened, edited and reloaded: Fear & Hunger, Fear & Hunger 2: Termina (RPG Maker MV) and Look Outside (RPG Maker MZ).
Skeleton profiles ship for OMORI, The Coffin of Andy and Leyley, The Witch's House
MV, Ib (2022 remake) and Little One. These are marked SKELETON in the picker: nobody
has round-tripped a real save through them yet, so their labels and state grouping are unchecked.
The names you see are still read from the game's own data files, so they're accurate either way.
And if your game has no profile at all, the two Any RPG Maker MV / MZ game entries work anyway — see Adding another game below.
Everything runs 100% in your browser. Your save file is never uploaded anywhere.
▶ Open SaveDelver — or download the repo and
double-click index.html. Both are the same tool; see Hosted or local? below for the one
difference.
- Back up your save first. Always keep a copy of the original save (
.rpgsave/.rmmzsave). - Open the hosted copy, or
index.htmlfrom a downloaded copy (double-click it — no install, no server needed). - Pick your game (Fear & Hunger, Termina, or Look Outside).
- Give it the files it asks for:
- The save file — a slot such as
file1.rpgsave/file1.rmmzsave(see locations below). - The game's data files — click the “Select your … folder” button (the app names the
right folder:
www\datafor the F&H games,datafor Look Outside), or drag the individual.jsonfiles onto the checklist. These let the editor show real names instead of numbers.
- The save file — a slot such as
- Click Open editor and make your changes.
- No save file? You can still click Browse game data -- the editor opens in a read-only
reference mode showing the skill tree, switches and variables. These games ration saving, so
if you cannot save in-game yet,
tools/Mod swapper.batinstalls a mod that lifts the limit (backing up your originals first).
- No save file? You can still click Browse game data -- the editor opens in a read-only
reference mode showing the skill tree, switches and variables. These games ration saving, so
if you cannot save in-game yet,
- Click Download, then copy the downloaded file back into your save folder (F&H:
www\save; Look Outside:save), replacing the slot you edited.
…\Steam\steamapps\common\Fear & Hunger\www\save\file1.rpgsave (MV)
…\Steam\steamapps\common\Fear & Hunger 2 Termina\www\save\file1.rpgsave (MV)
…\Steam\steamapps\common\Look Outside\save\file1.rmmzsave (MZ — note: no www)
Tip: if the folder picker is blocked when opening straight from disk, just drag the eight
.jsonfiles (System, Actors, Classes, Skills, States, Items, Weapons, Armors) onto the checklist instead — that always works.
The character list is grouped In your party (leader first, then marching order) and Elsewhere in this save, and the editor opens on the party leader. A save keeps a record for every character the story has touched, so opening on "the lowest actor id" landed on someone you were not playing -- Levi instead of Marcoh in Termina, the Mercenary instead of the Dark Priest in Fear & Hunger. If you do select someone outside the party, the panel says so and lists who your party actually is.
- Characters — name, nickname, class, level (exp kept in sync), current HP/MP/TP (labelled per game — Body/Mind for F&H, Health/Stamina/Ammo for Look Outside), and all eight parameter bonuses. Each vital shows its maximum and there is a Max all vitals button, computed the way the engine does: the class curve at that level, plus the actor bonus, plus every equipped item. Gear matters — one Look Outside character is wearing a weapon worth +999 max HP.
- Skills & abilities — add any skill from a searchable list, remove learned ones. Raising a
character's level also offers the skills their class teaches on the way up: the engine grants
those during
levelUp, which setting_levelin an editor never runs, so a levelled-up character would otherwise silently miss them. Barely matters in F&H (16 class learnings in the whole game) and matters a lot in Look Outside (116 — the Creep alone teaches 17). - States — afflictions, sickness (Infection, Parasites, Spore Poison), Hunger/Fear/Survival
levels, and mental states — grouped per game and toggleable. Adding a state writes the same turn
and step counters the engine itself would (
minTurns/stepsToRemove), so it wears off normally. - Limbs & dismemberment (Fear & Hunger 1 & 2) — its own panel, because a lost limb is stored
twice: as a state (the mechanical penalty) and as a switch that swaps in a limbless walking
sprite (
$cahara1_arm1,$knight_legsoff). Clearing the state alone leaves the character maimed on screen. Restore every limb clears both halves at once. The switch ids are verified per character against each game's ownSystem.json— F&H names them after the character's class (mercenary_arm1for Cahara,occultist_leg1for Marina), and the separate*_sawing_*mechanic is deliberately left alone. - Equipment — every equip slot the game defines (five for F&H, seven for Look Outside).
- Party — gold, full inventory (items / weapons / armors) picked from a radial wheel, and the
active roster. The wheel shows a window of entries curving past a fixed pointer rather than all
200-odd at once; typing spins it to the best match, Enter adds, and arrows or the scroll wheel
nudge it when you would know the thing on sight but cannot name it.
Each bag also has two bulk buttons: top up what you already hold to 99, and give me every
entry at 99 (which asks first -- it pulls in key and quest items too, so it is really a testing
tool). 99 is the engine ceiling: Game_Party.maxItems returns 99 in both MV and MZ, so a bigger
number would just be clamped. The roster
offers the whole cast, not just characters this playthrough has met: RPG Maker builds a
missing actor on demand, so someone you've never encountered joins at their default level and
gear. They're marked
freshvsin saveso you know which is which. - The Hexen (both Fear & Hunger games) — the skill tree as a clickable board. Clicking a node
grants the skill and sets its purchase switch, which is what the in-game table reads to know
a node was bought; writing only the skill leaves the game still offering it for sale. Prerequisite
edges are drawn, locked nodes are dimmed, and buying out of order asks first. The board is drawn
from the extracted coordinates, not from the game's art — nothing is copied out of your install,
and a node's circle is its click target, so nothing can drift out of alignment.
The two games' trees are built completely differently and both are supported: F&H1's 26 nodes
around an octagon of soul hubs, and Termina's 104-node map where a node may raise a parameter
instead of granting a skill (drawn as a square), the roots gate on a god's affliction level
(editable right there), and 17 nodes record who bought them in a
learns_*variable, which gets written too. With 104 nodes only the ones your playthrough has touched are labelled by default — hover for the rest, or tick label every node. Note the two independent facts it shows: the purchase switch is global to the playthrough, while the skill itself only sits on whoever was active at the time — so "bought by another character" is a normal state, not damage. Removing a skill only clears the purchase switch when no other character still has it. - Where you are in the run (Termina) — the game keeps its 3-day clock purely in switches:
one of DAY1/2/3, one of afternoon/dusk/evening, and the matching combined marker. Shown as a
3x3 grid, because most combinations are states the game can never be in; picking a square sets
all three the way the game does. Sleeping costs one phase — that is literally one call to the
::::DAYS_GO_BY_TOO_FASTevent. - Game systems (Look Outside) — the mechanics a game keeps scattered across ~1000 switches and
variables, gathered into named groups instead of numbered rows: crafting recipes (all 16, plus
the kit that has to be found first), the cooking sub-skill, Eugene's shop level and takings,
the exploration/danger clock and darkness, and the transformation. Groups are matched by
name, not id, so a patch renumbering things doesn't silently mis-target them. Values that aren't
scalars are shown read-only —
roomExplorationis a 457-entry array of per-room flags, and a number box would destroy it — and transient display state (whatever the shop UI last drew) is left out entirely, since editing it does nothing. - Variables & switches — searchable, showing the game's real names (e.g.
HUNGER,coin_flip), so you can flip story flags and counters. RPG Maker stores no notes for these — System.json holds a bare name and nothing else — so each row carries an ⓘ that reports where the game actually uses it: how often it's written and tested, the values it's set to and compared against, and which maps or common events touch it. That turns an opaque name into something readable:HUNGER_MERCis compared against 63/68/78/88/108/128 inside HUNGER LEVELS_Mercenary — those are the hunger breakpoints — whilePICTURE_fade_inturns out to be a two-use cutscene flag andSleep_cool_downa real mechanic tested 66 times across 13 maps.
Two separate things are kept in this browser's own storage (IndexedDB). Nothing leaves your machine.
The data library, per game, kept indefinitely. A game's data folder doesn't change between
playthroughs, so the first time you provide it the editor remembers it — and every later visit
fills the checklist in for you, leaving only the save file to drop. It's saved the moment a game's
required set is complete, not when you open the editor, so picking the folder and then closing
the tab still counts. Each game is remembered separately, so editing one never evicts another. The
intake says what it remembered and offers forget them; dropping a fresh folder replaces it,
which is what you want after the game updates.
The session in progress, so a crash costs nothing. Your save and every edit are kept as you work. Come back and the picker offers Restore or Discard. A restored session shows a banner reminding you those edits only ever existed in the browser: download the file and load it once in-game before relying on it. This one is a single slot — starting a new edit replaces it — and it survives a download, so a later crash can still recover.
Where storage is unavailable (a private window, blocked site data, or a browser that disallows
IndexedDB on file://) every call degrades quietly and the editor works exactly as before, just
without remembering anything.
Fields the editor doesn't touch are preserved exactly, so custom-plugin data stays intact.
The same static files either way, and in both cases your save never leaves your machine — the
editor makes no network requests at all, so there is no server to send it to. You can check that
claim: node tools/tests/test-hosting.js fails the build if any shipped file so much as mentions
an external URL.
| Hosted | Downloaded | |
|---|---|---|
| Editing saves, skill trees, everything | ✅ | ✅ |
The www\data folder picker |
✅ (better) | file:// — drag the JSON files instead |
| Session recovery if the tab dies | ✅ (better) | file:// |
The mod swapper (tools\Mod swapper.bat) |
❌ | ✅ |
The mod swapper is the only real difference. It installs a mod that lifts these games' saving
limits, and a web page cannot write into a Steam folder — browsers block the File System Access
API for system directories like Program Files outright. So it is a small Windows script that
ships with the download, and the hosted Mods tab says so rather than offering a button that
would silently fail.
There is no build step. Any static host works — copy the repo and serve it:
python -m http.server 8921 # then open http://localhost:8921Serve it over HTTPS if it is public: the clipboard helpers need a secure context, and the browser storage APIs are happier there too. The initial load is ~290 KB; the per-game usage indexes (another ~760 KB total) are fetched lazily, only for the game actually opened.
node tools/tests/run-all.js # everything, with a summary
node tools/tests/test-profiles.js # just one suiteMany suites check the editor against the real data files a game ships, which is the point of
them — a profile that matches nothing in System.json is exactly the bug worth catching. Those
suites find your installs automatically (Steam libraries across all drives) and skip cleanly
when a game is not present, so the suite runs whether you own three of these games or none:
SAVEDELVER_FH1="D:/Games/Fear & Hunger/www" node tools/tests/test-fh-edits.js
SAVEDELVER_STEAM="D:/SteamLibrary/steamapps/common" node tools/tests/test-systems.jsWith all three games installed the suite is 376 checks across fifteen files; with none, 74 of them still run — which is what CI does on every push.
run-all.js exits non-zero only on a real failure, never on a skip, and also runs
scan-escapes.js — a lint for one specific bug that bit this project repeatedly: a string literal
that lost a backslash, turning 'www\\data' into 'www\data', which JavaScript quietly reads as
"wwwdata" (and 'www\\files' into a literal form feed).
No game files. No art, no audio, no scripts, no data/*.json — nothing from any game. The
editor reads the copy you already own. .gitignore is set up to keep saves and game data out even
if you run the tools in place.
js/games/usage-*.js and hexen-fh*.js are indexes derived from game event data — names, ids,
reference counts and node coordinates, the same reference material a wiki publishes. See
NOTICE.md.
Each game is a small profile in js/games/ — fear-and-hunger.js, fear-and-hunger-2.js (MV) and
look-outside.js (MZ) are working examples. To add a game, copy one, adjust the title / detect /
labels / state groups, and add a <script> tag for it in index.html. The codecs, data loader,
and every editor are shared, so a same-engine game mostly just needs its labels and state groupings.
For a different engine, also set engine (rpgmv/rpgmz), saveExt, and dataFolderLabel.
A profile can also declare systems: named groups of switches and variables that make up one
mechanic, matched by name pattern. The shared systems editor renders them, picks the right control
per value type, and refuses to offer arrays or objects as scalars. look-outside.js is the worked
example.
- RPG Maker MV (
.rpgsave):LZString.compressToBase64(JsonEx.stringify(state))— text, re-encoded with the exactlz-stringthe game ships (js/vendor/lz-string.js). - RPG Maker MZ (
.rmmzsave): pako/zlib-deflated JSON stored as a UTF-8-wrapped binary string — read as binary, re-encoded with the game's ownpako(js/vendor/pako.min.js). - The codec is detected from the save file, not from the profile. Saves are always read as an
ArrayBuffer and
decodeAuto()sniffs the real format (extension, then a leading0x78zlib header, then simply trying both), and rejects anything that decodes to a non-save. A profile'sengineis only an ordering hint — so a skeleton that guesses the wrong engine still opens and re-saves the file correctly, and the download is named with the extension that actually applies. - It never reconstructs game classes: it edits leaf values in place and leaves JsonEx's
@/@c/@a/@rmarkers untouched. (Integer-valued floats like HP100.0come back as100— the same number; the game rewrites them on its next save.) - No build step, no dependencies, no network. Just static files.
index.html app shell + views
css/style.css dark theme
js/vendor/lz-string.js MV compressor (vendored)
js/vendor/pako.min.js MZ compressor (vendored)
js/util.js DOM helpers + the searchable "adder" widget
js/widgets/wheel.js radial item picker (search spins it)
js/cache.js IndexedDB crash-recovery for the session in progress
js/usage.js lazy loader + UI for the "where is this used?" index
js/jsonex.js JsonEx @a/@c navigation helpers
js/rpgsave.js engine-aware codecs (MV lz-string · MZ pako)
js/mvdata.js indexes the game's data JSON into id→name lookups
js/gameRegistry.js registry + skeleton() helper for unverified profiles
js/games/_shared.js generic state grouping + limb (state↔switch) resolution
js/games/_generic.js the "Any RPG Maker MV / MZ game" catch-alls
js/games/*.js profiles: F&H, Termina (MV) · Look Outside (MZ) · skeletons
js/games/hexen-fh*.js extracted hexen trees, F&H1 + Termina (coordinates + ids, no art)
js/games/usage-*.js switch/variable usage indexes (lazy-loaded, not in index.html)
js/editors/*.js characters · hexen · party · systems · variables · switches
tools/modswap.ps1 reversible mod installer (backup -> swap -> restore)
js/app.js controller: picker → intake → editor → download
tools/tests/run-all.js run every suite (skips games you do not own)
tools/ offline extractors (decrypt .rpgmvp, rebuild the hexen tree)
MIT — see LICENSE. Bundled libraries, derived reference data and game-name usage are covered in NOTICE.md. Unaffiliated with, and unendorsed by, the developers of any game listed here.