modwright 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +35 -0
- package/README.md +212 -0
- package/assets/claude/agents/mw-explore.md +46 -0
- package/assets/claude/agents/mw-fixture.md +33 -0
- package/assets/claude/agents/mw-rule-author.md +51 -0
- package/assets/claude/agents/mw-scaffold-author.md +48 -0
- package/assets/claude/skills/mw-author.md +59 -0
- package/assets/claude/skills/mw-new-item.md +51 -0
- package/assets/claude/skills/mw-new-spell.md +50 -0
- package/assets/claude/skills/mw-scaffold.md +59 -0
- package/assets/claude/skills/mw-ship.md +57 -0
- package/assets/claude/skills/mw-validate.md +51 -0
- package/assets/claude/skills/mw-verify.md +59 -0
- package/assets/nivalisnights/extract_resources.py +177 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Config.json +5 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/BootstrapClient.lua +55 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/BootstrapServer.lua +81 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Log.lua +96 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Probes.lua +1038 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/ProbesClient.lua +74 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Protocol.lua +985 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/ScriptExtender/Lua/ModWrightBridge/Watch.lua +175 -0
- package/bridges/bg3-se/Mods/ModWrightBridge/meta.lsx +45 -0
- package/bridges/bg3-se/README.md +99 -0
- package/bridges/bg3-se/bridge.json +68 -0
- package/bridges/cp2077-cet/ModWrightBridge/init.lua +375 -0
- package/bridges/cp2077-cet/ModWrightBridge/probes.lua +1104 -0
- package/bridges/cp2077-cet/ModWrightBridge/protocol.lua +1306 -0
- package/bridges/cp2077-cet/README.md +165 -0
- package/bridges/cp2077-cet/bridge.json +53 -0
- package/dist/core/bridge/arm.js +175 -0
- package/dist/core/bridge/cet-console.js +26 -0
- package/dist/core/bridge/cet-log.js +362 -0
- package/dist/core/bridge/index.js +11 -0
- package/dist/core/bridge/locate.js +35 -0
- package/dist/core/bridge/paths.js +34 -0
- package/dist/core/bridge/pending.js +89 -0
- package/dist/core/bridge/poll.js +155 -0
- package/dist/core/bridge/stage.js +100 -0
- package/dist/core/bridge/status.js +97 -0
- package/dist/core/bridge/types.js +145 -0
- package/dist/core/bridge/validate.js +107 -0
- package/dist/core/build/index.js +6 -0
- package/dist/core/build/manifest.js +47 -0
- package/dist/core/build/paths.js +32 -0
- package/dist/core/build/run.js +342 -0
- package/dist/core/build/stage.js +265 -0
- package/dist/core/build/steps/bg3.js +129 -0
- package/dist/core/build/steps/core.js +195 -0
- package/dist/core/build/steps/cyberpunk.js +95 -0
- package/dist/core/build/steps/listing.js +35 -0
- package/dist/core/build/types.js +13 -0
- package/dist/core/build/zip.js +148 -0
- package/dist/core/compat/check.js +113 -0
- package/dist/core/compat/pe.js +220 -0
- package/dist/core/compat/types.js +1 -0
- package/dist/core/compat/version.js +70 -0
- package/dist/core/deploy/guards.js +292 -0
- package/dist/core/deploy/index.js +5 -0
- package/dist/core/deploy/plan.js +696 -0
- package/dist/core/deploy/reload-apply.js +361 -0
- package/dist/core/deploy/reload.js +358 -0
- package/dist/core/deploy/sources.js +169 -0
- package/dist/core/deploy/types.js +1 -0
- package/dist/core/epic.js +54 -0
- package/dist/core/fsutil.js +191 -0
- package/dist/core/home.js +70 -0
- package/dist/core/knowledge/facts.js +229 -0
- package/dist/core/knowledge/index.js +4 -0
- package/dist/core/knowledge/search.js +112 -0
- package/dist/core/knowledge/store.js +123 -0
- package/dist/core/knowledge/types.js +1 -0
- package/dist/core/ledger/check.js +42 -0
- package/dist/core/ledger/hooks.js +80 -0
- package/dist/core/ledger/index.js +7 -0
- package/dist/core/ledger/query.js +17 -0
- package/dist/core/ledger/record.js +84 -0
- package/dist/core/ledger/status.js +53 -0
- package/dist/core/ledger/store.js +98 -0
- package/dist/core/ledger/types.js +108 -0
- package/dist/core/logs/index.js +4 -0
- package/dist/core/logs/registry.js +50 -0
- package/dist/core/logs/scan.js +195 -0
- package/dist/core/logs/triage.js +160 -0
- package/dist/core/logs/types.js +1 -0
- package/dist/core/lsx.js +10 -0
- package/dist/core/lz4.js +66 -0
- package/dist/core/mods.js +229 -0
- package/dist/core/process.js +49 -0
- package/dist/core/project/build-steps.js +83 -0
- package/dist/core/project/describe.js +74 -0
- package/dist/core/project/index.js +5 -0
- package/dist/core/project/load.js +146 -0
- package/dist/core/project/schema.js +264 -0
- package/dist/core/project/types.js +3 -0
- package/dist/core/prompts.js +72 -0
- package/dist/core/registry.js +35 -0
- package/dist/core/safety/backup.js +206 -0
- package/dist/core/safety/execute.js +188 -0
- package/dist/core/safety/index.js +5 -0
- package/dist/core/safety/plan.js +122 -0
- package/dist/core/safety/restore.js +172 -0
- package/dist/core/safety/types.js +1 -0
- package/dist/core/scaffold/bootstrap.js +7 -0
- package/dist/core/scaffold/catalog.js +28 -0
- package/dist/core/scaffold/claude-assets.js +271 -0
- package/dist/core/scaffold/collisions.js +64 -0
- package/dist/core/scaffold/emit.js +356 -0
- package/dist/core/scaffold/engine.js +680 -0
- package/dist/core/scaffold/ids.js +78 -0
- package/dist/core/scaffold/index.js +10 -0
- package/dist/core/scaffold/jsonpath.js +121 -0
- package/dist/core/scaffold/load.js +81 -0
- package/dist/core/scaffold/render.js +85 -0
- package/dist/core/scaffold/sequence.js +396 -0
- package/dist/core/scaffold/types.js +309 -0
- package/dist/core/steam.js +63 -0
- package/dist/core/surfaceutil.js +36 -0
- package/dist/core/testplan/check.js +67 -0
- package/dist/core/testplan/index.js +5 -0
- package/dist/core/testplan/load.js +100 -0
- package/dist/core/testplan/registry.js +317 -0
- package/dist/core/testplan/run.js +389 -0
- package/dist/core/testplan/types.js +82 -0
- package/dist/core/text/converters/bg3.js +50 -0
- package/dist/core/text/converters/cyberpunk.js +36 -0
- package/dist/core/text/converters/index.js +261 -0
- package/dist/core/text/diff/cr2w.js +180 -0
- package/dist/core/text/diff/index.js +16 -0
- package/dist/core/text/diff/loca.js +43 -0
- package/dist/core/text/diff/lsx.js +126 -0
- package/dist/core/text/handles.js +86 -0
- package/dist/core/text/index.js +6 -0
- package/dist/core/text/json.js +46 -0
- package/dist/core/text/templates/cache.js +71 -0
- package/dist/core/text/templates/index.js +3 -0
- package/dist/core/text/templates/library.js +245 -0
- package/dist/core/text/templates/types.js +51 -0
- package/dist/core/text/toolchain.js +16 -0
- package/dist/core/text/types.js +1 -0
- package/dist/core/text/validate.js +149 -0
- package/dist/core/text/xml.js +58 -0
- package/dist/core/toolchain/datafetch.js +151 -0
- package/dist/core/toolchain/env.js +63 -0
- package/dist/core/toolchain/features.js +170 -0
- package/dist/core/toolchain/index.js +8 -0
- package/dist/core/toolchain/install.js +191 -0
- package/dist/core/toolchain/locate.js +275 -0
- package/dist/core/toolchain/remember.js +84 -0
- package/dist/core/toolchain/run.js +318 -0
- package/dist/core/toolchain/specs.js +351 -0
- package/dist/core/toolchain/types.js +1 -0
- package/dist/core/types.js +1 -0
- package/dist/core/userconfig.js +66 -0
- package/dist/core/validate/context.js +139 -0
- package/dist/core/validate/index.js +5 -0
- package/dist/core/validate/registry.js +58 -0
- package/dist/core/validate/run.js +131 -0
- package/dist/core/validate/suppressions.js +91 -0
- package/dist/core/validate/types.js +2 -0
- package/dist/core/yamledit.js +51 -0
- package/dist/index.js +389 -0
- package/dist/server.js +1914 -0
- package/dist/surfaces/baldursgate3/compat.js +164 -0
- package/dist/surfaces/baldursgate3/identity.js +110 -0
- package/dist/surfaces/baldursgate3/index/build.js +331 -0
- package/dist/surfaces/baldursgate3/index/index.js +17 -0
- package/dist/surfaces/baldursgate3/index/info.js +40 -0
- package/dist/surfaces/baldursgate3/index/parsers/loca.js +41 -0
- package/dist/surfaces/baldursgate3/index/parsers/lsx.js +137 -0
- package/dist/surfaces/baldursgate3/index/parsers/stats.js +45 -0
- package/dist/surfaces/baldursgate3/index/parsers/treasuretable.js +57 -0
- package/dist/surfaces/baldursgate3/index/parsers/xmlutil.js +142 -0
- package/dist/surfaces/baldursgate3/index/queries.js +327 -0
- package/dist/surfaces/baldursgate3/index/schema.js +62 -0
- package/dist/surfaces/baldursgate3/index.js +3 -0
- package/dist/surfaces/baldursgate3/logs.js +278 -0
- package/dist/surfaces/baldursgate3/modsettings.js +115 -0
- package/dist/surfaces/baldursgate3/pak.js +153 -0
- package/dist/surfaces/baldursgate3/settings.js +49 -0
- package/dist/surfaces/baldursgate3/surface.js +232 -0
- package/dist/surfaces/baldursgate3/validators/bridge.js +7 -0
- package/dist/surfaces/baldursgate3/validators/files.js +476 -0
- package/dist/surfaces/baldursgate3/validators/items.js +1001 -0
- package/dist/surfaces/baldursgate3/validators/progression.js +734 -0
- package/dist/surfaces/baldursgate3/validators/stats.js +1076 -0
- package/dist/surfaces/baldursgate3/validators/story.js +790 -0
- package/dist/surfaces/baldursgate3/validators/templates.js +7 -0
- package/dist/surfaces/cyberpunk2077/compat.js +223 -0
- package/dist/surfaces/cyberpunk2077/index/build.js +231 -0
- package/dist/surfaces/cyberpunk2077/index/index.js +17 -0
- package/dist/surfaces/cyberpunk2077/index/info.js +51 -0
- package/dist/surfaces/cyberpunk2077/index/model.js +52 -0
- package/dist/surfaces/cyberpunk2077/index/parsers/tweak.js +483 -0
- package/dist/surfaces/cyberpunk2077/index/parsers/tweakxl-yaml.js +183 -0
- package/dist/surfaces/cyberpunk2077/index/queries.js +504 -0
- package/dist/surfaces/cyberpunk2077/index/resource.js +135 -0
- package/dist/surfaces/cyberpunk2077/index/schema.js +90 -0
- package/dist/surfaces/cyberpunk2077/index.js +3 -0
- package/dist/surfaces/cyberpunk2077/logs.js +742 -0
- package/dist/surfaces/cyberpunk2077/paths.js +12 -0
- package/dist/surfaces/cyberpunk2077/surface.js +218 -0
- package/dist/surfaces/cyberpunk2077/validators/bridge.js +7 -0
- package/dist/surfaces/cyberpunk2077/validators/cr2w.js +349 -0
- package/dist/surfaces/cyberpunk2077/validators/garments.js +1181 -0
- package/dist/surfaces/cyberpunk2077/validators/mesh.js +338 -0
- package/dist/surfaces/cyberpunk2077/validators/modsettings.js +120 -0
- package/dist/surfaces/cyberpunk2077/validators/packaging.js +463 -0
- package/dist/surfaces/cyberpunk2077/validators/red4ext.js +318 -0
- package/dist/surfaces/cyberpunk2077/validators/redscript.js +193 -0
- package/dist/surfaces/cyberpunk2077/validators/templates.js +7 -0
- package/dist/surfaces/cyberpunk2077/validators/tweaks.js +768 -0
- package/dist/surfaces/cyberpunk2077/validators/vehicles.js +531 -0
- package/dist/surfaces/cyberpunk2077/validators/xl.js +308 -0
- package/dist/surfaces/eldenring/binders.js +111 -0
- package/dist/surfaces/eldenring/compat.js +166 -0
- package/dist/surfaces/eldenring/dcx.js +49 -0
- package/dist/surfaces/eldenring/index.js +13 -0
- package/dist/surfaces/eldenring/loaders.js +132 -0
- package/dist/surfaces/eldenring/logs.js +67 -0
- package/dist/surfaces/eldenring/paramdef.js +256 -0
- package/dist/surfaces/eldenring/params.js +129 -0
- package/dist/surfaces/eldenring/surface.js +121 -0
- package/dist/surfaces/eldenring/tools.js +52 -0
- package/dist/surfaces/eldenring/validators/binders.js +193 -0
- package/dist/surfaces/eldenring/validators/packages.js +159 -0
- package/dist/surfaces/eldenring/validators/params.js +334 -0
- package/dist/surfaces/eldenring/validators/profiles.js +287 -0
- package/dist/surfaces/index.js +34 -0
- package/dist/surfaces/nivalisnights/compat.js +229 -0
- package/dist/surfaces/nivalisnights/index/build.js +310 -0
- package/dist/surfaces/nivalisnights/index/index.js +5 -0
- package/dist/surfaces/nivalisnights/index/queries.js +231 -0
- package/dist/surfaces/nivalisnights/index.js +4 -0
- package/dist/surfaces/nivalisnights/logs.js +473 -0
- package/dist/surfaces/nivalisnights/surface.js +195 -0
- package/dist/surfaces/skyrimse/archives.js +229 -0
- package/dist/surfaces/skyrimse/compat.js +163 -0
- package/dist/surfaces/skyrimse/index.js +12 -0
- package/dist/surfaces/skyrimse/loadorder.js +174 -0
- package/dist/surfaces/skyrimse/logs.js +241 -0
- package/dist/surfaces/skyrimse/plugins.js +149 -0
- package/dist/surfaces/skyrimse/records.js +94 -0
- package/dist/surfaces/skyrimse/surface.js +240 -0
- package/dist/surfaces/skyrimse/validators/archive-records.js +165 -0
- package/dist/surfaces/skyrimse/validators/archives.js +110 -0
- package/dist/surfaces/skyrimse/validators/plugins.js +374 -0
- package/dist/surfaces/skyrimse/validators/records.js +117 -0
- package/dist/surfaces/stardewvalley/compat.js +190 -0
- package/dist/surfaces/stardewvalley/config.js +42 -0
- package/dist/surfaces/stardewvalley/contentpatcher.js +203 -0
- package/dist/surfaces/stardewvalley/index/index.js +229 -0
- package/dist/surfaces/stardewvalley/index/wiki.js +190 -0
- package/dist/surfaces/stardewvalley/index.js +12 -0
- package/dist/surfaces/stardewvalley/logs.js +307 -0
- package/dist/surfaces/stardewvalley/mods.js +182 -0
- package/dist/surfaces/stardewvalley/surface.js +244 -0
- package/dist/surfaces/stardewvalley/validators/content.js +321 -0
- package/dist/surfaces/stardewvalley/validators/fields.js +147 -0
- package/dist/surfaces/stardewvalley/validators/loadorder.js +69 -0
- package/dist/surfaces/stardewvalley/validators/manifest.js +221 -0
- package/dist/surfaces/subnautica2/compat.js +138 -0
- package/dist/surfaces/subnautica2/index.js +5 -0
- package/dist/surfaces/subnautica2/logs.js +129 -0
- package/dist/surfaces/subnautica2/paks.js +173 -0
- package/dist/surfaces/subnautica2/surface.js +151 -0
- package/dist/surfaces/subnautica2/validators/packaging.js +298 -0
- package/dist/surfaces/valheim/compat.js +171 -0
- package/dist/surfaces/valheim/index/index.js +301 -0
- package/dist/surfaces/valheim/index/tables.js +103 -0
- package/dist/surfaces/valheim/index.js +11 -0
- package/dist/surfaces/valheim/logs.js +197 -0
- package/dist/surfaces/valheim/packaging.js +131 -0
- package/dist/surfaces/valheim/plugins.js +270 -0
- package/dist/surfaces/valheim/references.js +121 -0
- package/dist/surfaces/valheim/surface.js +223 -0
- package/dist/surfaces/valheim/validators/packaging.js +218 -0
- package/dist/surfaces/valheim/validators/plugins.js +287 -0
- package/dist/surfaces/valheim/validators/references.js +169 -0
- package/knowledge/baldursgate3/animations.gr2.yaml +166 -0
- package/knowledge/baldursgate3/audio.voice.yaml +182 -0
- package/knowledge/baldursgate3/audio.wwise.yaml +104 -0
- package/knowledge/baldursgate3/charactercreation.heads-hair.yaml +193 -0
- package/knowledge/baldursgate3/communitylibrary.shared-content.yaml +129 -0
- package/knowledge/baldursgate3/compatibilityframework.api.yaml +176 -0
- package/knowledge/baldursgate3/crash.causes.yaml +90 -0
- package/knowledge/baldursgate3/dialogue.dialogbank.yaml +120 -0
- package/knowledge/baldursgate3/dialogue.files.yaml +236 -0
- package/knowledge/baldursgate3/dialogue.osiris-goals.yaml +386 -0
- package/knowledge/baldursgate3/dialogue.yaml +122 -0
- package/knowledge/baldursgate3/feats.classes.yaml +164 -0
- package/knowledge/baldursgate3/items.cloth-physics.yaml +167 -0
- package/knowledge/baldursgate3/items.roottemplates.yaml +320 -0
- package/knowledge/baldursgate3/items.visualbank.yaml +628 -0
- package/knowledge/baldursgate3/journal.quests.yaml +214 -0
- package/knowledge/baldursgate3/loadorder.modsettings.yaml +128 -0
- package/knowledge/baldursgate3/localization.handles.yaml +92 -0
- package/knowledge/baldursgate3/misc.encoding-and-practice.yaml +111 -0
- package/knowledge/baldursgate3/origins.companions.yaml +144 -0
- package/knowledge/baldursgate3/osiris.signatures.yaml +211 -0
- package/knowledge/baldursgate3/packaging.meta.yaml +155 -0
- package/knowledge/baldursgate3/packaging.paks.yaml +79 -0
- package/knowledge/baldursgate3/process.launch.yaml +34 -0
- package/knowledge/baldursgate3/progressions.yaml +92 -0
- package/knowledge/baldursgate3/publishing.modio-nexus.yaml +170 -0
- package/knowledge/baldursgate3/publishing.toolkit-modio.yaml +135 -0
- package/knowledge/baldursgate3/races.progression.yaml +228 -0
- package/knowledge/baldursgate3/scriptextender.console.yaml +257 -0
- package/knowledge/baldursgate3/scriptextender.yaml +252 -0
- package/knowledge/baldursgate3/stats.boosts.yaml +293 -0
- package/knowledge/baldursgate3/stats.equipment-kits.yaml +69 -0
- package/knowledge/baldursgate3/stats.interrupts.yaml +45 -0
- package/knowledge/baldursgate3/stats.itemcombos.yaml +65 -0
- package/knowledge/baldursgate3/stats.spells.yaml +293 -0
- package/knowledge/baldursgate3/stats.weapons.yaml +210 -0
- package/knowledge/baldursgate3/toolchain.divine.yaml +179 -0
- package/knowledge/baldursgate3/toolchain.lslib-formats.yaml +242 -0
- package/knowledge/baldursgate3/toolkit.levels.yaml +177 -0
- package/knowledge/baldursgate3/ui.icons-atlas.yaml +78 -0
- package/knowledge/baldursgate3/ui.icons.yaml +412 -0
- package/knowledge/baldursgate3/ui.mcm.yaml +161 -0
- package/knowledge/baldursgate3/vfx.materials.yaml +174 -0
- package/knowledge/baldursgate3/visuals.characterfix.yaml +73 -0
- package/knowledge/cyberpunk2077/animations.anims.yaml +118 -0
- package/knowledge/cyberpunk2077/anims.archivexl.yaml +163 -0
- package/knowledge/cyberpunk2077/anims.authoring.yaml +579 -0
- package/knowledge/cyberpunk2077/anims.encoder.yaml +156 -0
- package/knowledge/cyberpunk2077/anims.graph.yaml +629 -0
- package/knowledge/cyberpunk2077/anims.method.yaml +360 -0
- package/knowledge/cyberpunk2077/anims.pipeline.yaml +352 -0
- package/knowledge/cyberpunk2077/anims.roundtrip.yaml +222 -0
- package/knowledge/cyberpunk2077/anims.sets.yaml +176 -0
- package/knowledge/cyberpunk2077/archivexl.bodytypes.yaml +149 -0
- package/knowledge/cyberpunk2077/archivexl.dynamic-appearances.yaml +218 -0
- package/knowledge/cyberpunk2077/archivexl.manifest.yaml +214 -0
- package/knowledge/cyberpunk2077/audio.events.yaml +168 -0
- package/knowledge/cyberpunk2077/audio.sounds.yaml +164 -0
- package/knowledge/cyberpunk2077/audio.voicesets.yaml +146 -0
- package/knowledge/cyberpunk2077/cet.sandbox.yaml +219 -0
- package/knowledge/cyberpunk2077/clothing.garments.yaml +283 -0
- package/knowledge/cyberpunk2077/clothing.refits.yaml +215 -0
- package/knowledge/cyberpunk2077/codeware.overview.yaml +111 -0
- package/knowledge/cyberpunk2077/codeware.systems.yaml +192 -0
- package/knowledge/cyberpunk2077/drones.combat.yaml +416 -0
- package/knowledge/cyberpunk2077/drones.control.yaml +552 -0
- package/knowledge/cyberpunk2077/entities.appearance.yaml +166 -0
- package/knowledge/cyberpunk2077/equipmentex.slots.yaml +151 -0
- package/knowledge/cyberpunk2077/fx.effects.yaml +246 -0
- package/knowledge/cyberpunk2077/fx.lights.yaml +171 -0
- package/knowledge/cyberpunk2077/hair.modding.yaml +145 -0
- package/knowledge/cyberpunk2077/items.wiring.yaml +246 -0
- package/knowledge/cyberpunk2077/loadorder.archives.yaml +71 -0
- package/knowledge/cyberpunk2077/mesh.blender.yaml +209 -0
- package/knowledge/cyberpunk2077/nativedb.dump.yaml +98 -0
- package/knowledge/cyberpunk2077/npc.appearance.yaml +275 -0
- package/knowledge/cyberpunk2077/npc.behaviour.yaml +128 -0
- package/knowledge/cyberpunk2077/npc.locomotion.yaml +490 -0
- package/knowledge/cyberpunk2077/packaging.deploy.yaml +175 -0
- package/knowledge/cyberpunk2077/packaging.variants.yaml +176 -0
- package/knowledge/cyberpunk2077/player.control.yaml +918 -0
- package/knowledge/cyberpunk2077/process.assetbuild.yaml +154 -0
- package/knowledge/cyberpunk2077/process.lessons.yaml +276 -0
- package/knowledge/cyberpunk2077/quests.minor.yaml +46 -0
- package/knowledge/cyberpunk2077/quests.scenes.yaml +282 -0
- package/knowledge/cyberpunk2077/quickhacks.tiers.yaml +41 -0
- package/knowledge/cyberpunk2077/red4ext.api.yaml +645 -0
- package/knowledge/cyberpunk2077/red4ext.plugins.yaml +124 -0
- package/knowledge/cyberpunk2077/redhottools.hotreload.yaml +245 -0
- package/knowledge/cyberpunk2077/redscript.compile-log.yaml +76 -0
- package/knowledge/cyberpunk2077/redscript.modules.yaml +118 -0
- package/knowledge/cyberpunk2077/toolchain.wolvenkit.yaml +163 -0
- package/knowledge/cyberpunk2077/tweakdb.loot-recipes.yaml +184 -0
- package/knowledge/cyberpunk2077/tweakdb.melee.yaml +352 -0
- package/knowledge/cyberpunk2077/tweakdb.weapons.yaml +325 -0
- package/knowledge/cyberpunk2077/tweakxl.hotreload.yaml +151 -0
- package/knowledge/cyberpunk2077/tweakxl.yaml-syntax.yaml +208 -0
- package/knowledge/cyberpunk2077/ui.icons.yaml +259 -0
- package/knowledge/cyberpunk2077/ui.inkatlas.yaml +81 -0
- package/knowledge/cyberpunk2077/ui.modsettings.yaml +204 -0
- package/knowledge/cyberpunk2077/vehicles.control.yaml +475 -0
- package/knowledge/cyberpunk2077/vehicles.dashboard-ui.yaml +203 -0
- package/knowledge/cyberpunk2077/vehicles.entities.yaml +195 -0
- package/knowledge/cyberpunk2077/vehicles.wiring.yaml +137 -0
- package/knowledge/cyberpunk2077/wolvenkit.cli.yaml +167 -0
- package/knowledge/cyberpunk2077/workspot.system.yaml +55 -0
- package/knowledge/cyberpunk2077/world.interactions.yaml +41 -0
- package/knowledge/cyberpunk2077/world.loot-container.yaml +167 -0
- package/knowledge/cyberpunk2077/world.sectors.yaml +233 -0
- package/knowledge/eldenring/formats.binders.yaml +237 -0
- package/knowledge/eldenring/launcher.me3.yaml +230 -0
- package/knowledge/eldenring/launcher.modengine2.yaml +119 -0
- package/knowledge/eldenring/params.paramdef.yaml +149 -0
- package/knowledge/eldenring/params.regulation.yaml +142 -0
- package/knowledge/eldenring/saves.online.yaml +118 -0
- package/knowledge/eldenring/toolchain.cli.yaml +256 -0
- package/knowledge/nivalisnights/modding.runtime.yaml +157 -0
- package/knowledge/skyrimse/archives.bsa.yaml +212 -0
- package/knowledge/skyrimse/install.detection.yaml +41 -0
- package/knowledge/skyrimse/loadorder.files.yaml +242 -0
- package/knowledge/skyrimse/plugins.esl.yaml +189 -0
- package/knowledge/skyrimse/plugins.format.yaml +224 -0
- package/knowledge/skyrimse/skse.runtime.yaml +283 -0
- package/knowledge/skyrimse/toolchain.xedit-spriggit.yaml +336 -0
- package/knowledge/stardewvalley/contentpatcher.format.yaml +338 -0
- package/knowledge/stardewvalley/distribution.channels.yaml +236 -0
- package/knowledge/stardewvalley/game.versions.yaml +202 -0
- package/knowledge/stardewvalley/install.layout.yaml +277 -0
- package/knowledge/stardewvalley/smapi.loader.yaml +284 -0
- package/knowledge/stardewvalley/smapi.logs.yaml +329 -0
- package/knowledge/stardewvalley/smapi.manifest.yaml +293 -0
- package/knowledge/stardewvalley/toolchain.build.yaml +261 -0
- package/knowledge/stardewvalley/wiki.dataformat.yaml +130 -0
- package/knowledge/subnautica2/game.build.yaml +331 -0
- package/knowledge/subnautica2/modding.state.yaml +210 -0
- package/knowledge/subnautica2/ue5.containers.yaml +72 -0
- package/knowledge/subnautica2/ue5.paks.yaml +203 -0
- package/knowledge/subnautica2/ue5.tooling.yaml +175 -0
- package/knowledge/subnautica2/ue5.ue4ss.yaml +203 -0
- package/knowledge/valheim/bepinex.loader.yaml +247 -0
- package/knowledge/valheim/bepinex.plugins.yaml +251 -0
- package/knowledge/valheim/game.versions.yaml +321 -0
- package/knowledge/valheim/install.layout.yaml +216 -0
- package/knowledge/valheim/jotunn.library.yaml +334 -0
- package/knowledge/valheim/thunderstore.packaging.yaml +217 -0
- package/knowledge/valheim/toolchain.build.yaml +111 -0
- package/package.json +29 -0
- package/scaffolds/baldursgate3/new-class-injection.yaml +148 -0
- package/scaffolds/baldursgate3/new-item.yaml +264 -0
- package/scaffolds/baldursgate3/new-mod.yaml +174 -0
- package/scaffolds/baldursgate3/new-passive.yaml +100 -0
- package/scaffolds/baldursgate3/new-project.yaml +118 -0
- package/scaffolds/baldursgate3/new-quest-stub.yaml +159 -0
- package/scaffolds/baldursgate3/new-spell.yaml +102 -0
- package/scaffolds/baldursgate3/new-status.yaml +119 -0
- package/scaffolds/baldursgate3/sequences/subclass-kit.yaml +50 -0
- package/scaffolds/cyberpunk2077/edit-tweak.yaml +70 -0
- package/scaffolds/cyberpunk2077/mesh-export-preset.yaml +170 -0
- package/scaffolds/cyberpunk2077/new-entity-patch.yaml +255 -0
- package/scaffolds/cyberpunk2077/new-garment-refit.yaml +279 -0
- package/scaffolds/cyberpunk2077/new-item-chain.yaml +548 -0
- package/scaffolds/cyberpunk2077/new-localization.yaml +130 -0
- package/scaffolds/cyberpunk2077/new-mod-settings.yaml +133 -0
- package/scaffolds/cyberpunk2077/new-player-replacer.yaml +1003 -0
- package/scaffolds/cyberpunk2077/new-project.yaml +157 -0
- package/scaffolds/cyberpunk2077/new-sector-node.yaml +156 -0
- package/scaffolds/cyberpunk2077/new-tweak.yaml +121 -0
- package/scaffolds/cyberpunk2077/new-vehicle-livery.yaml +148 -0
- package/scaffolds/cyberpunk2077/new-workspot-entity.yaml +177 -0
- package/scaffolds/cyberpunk2077/sequences/iconic-weapon.yaml +72 -0
- package/scaffolds/cyberpunk2077/sequences/quickhack-takeover.yaml +213 -0
- package/scaffolds/stardewvalley/new-cp-patch.yaml +106 -0
- package/scaffolds/stardewvalley/new-csharp-mod.yaml +195 -0
- package/scaffolds/stardewvalley/new-project.yaml +184 -0
- package/scaffolds/stardewvalley/sequences/content-pack.yaml +31 -0
- package/scripts/mw-tool.mjs +184 -0
|
@@ -0,0 +1,256 @@
|
|
|
1
|
+
game: eldenring
|
|
2
|
+
topic: toolchain.cli
|
|
3
|
+
title: which elden ring tools can run unattended, and which cannot
|
|
4
|
+
facts:
|
|
5
|
+
- id: eldenring.toolchain.witchybnd-has-a-real-headless-mode
|
|
6
|
+
claim: WitchyBND is the unpack/repack CLI for Elden Ring binder and texture formats and it supports
|
|
7
|
+
genuine unattended use — `-p/--passive` suppresses every prompt and delay, `-s/--silent`
|
|
8
|
+
suppresses console output and implies passive, and `-u/--unpack` or `-r/--repack` pin the
|
|
9
|
+
direction so it cannot guess wrong.
|
|
10
|
+
status: community
|
|
11
|
+
source: "`public class CliOptions` in
|
|
12
|
+
https://github.com/ividyon/WitchyBND/blob/main/WitchyBND/Configuration.cs — `-p, --passive`
|
|
13
|
+
\"Will not prompt the user for any input or cause any delays. Suited for automatic execution
|
|
14
|
+
in scripts.\"; `-s, --silent` \"Will not print any console output. Inherently sets 'passive'
|
|
15
|
+
to true.\"; `-u, --unpack` \"Only perform unpack processing, no repacking.\"; `-r, --repack`
|
|
16
|
+
\"Only perform repack processing, no unpacking.\"; also `-c, --recursive`, `-d, --dcx`, `-f,
|
|
17
|
+
--flexible`, `-l, --location`, `-v, --version`"
|
|
18
|
+
tags:
|
|
19
|
+
- witchybnd
|
|
20
|
+
- cli
|
|
21
|
+
- unattended
|
|
22
|
+
- passive
|
|
23
|
+
- silent
|
|
24
|
+
- toolchain
|
|
25
|
+
- flags
|
|
26
|
+
detail: Note the flag trap - `-c` is `--recursive`, not a "cli mode" switch; there is no `--cli`.
|
|
27
|
+
The Explorer context-menu integration lives in a separate opt-in assembly, so nothing forces
|
|
28
|
+
an interactive screen. Latest release at the time of writing is 3.0.1.0 (2026-07-06), with
|
|
29
|
+
both win-x64 and linux-x64 builds, licensed GPL v3. README format list - "DCX, FFXBND, BND3,
|
|
30
|
+
BND4, BXF3, BXF4, FFXDLSE, FMG, GPARAM, LUAGNL, LUAINFO, TPF, Zero3, FXR1, FXR3, MATBIN, MTD,
|
|
31
|
+
PARAM, MQB, and ENTRYFILELIST".
|
|
32
|
+
- id: eldenring.toolchain.witchybnd-xml-is-the-text-converter
|
|
33
|
+
claim: "WitchyBND's round trip is the Elden Ring equivalent of WolvenKit's cr2w-to-json and divine's
|
|
34
|
+
lsf-to-lsx: unpacking a binder writes a sidecar manifest named `_witchy-<tag>.xml` beside the
|
|
35
|
+
extracted entries, and repacking reads it back. For a regulation/PARAMBND4 the sidecar is
|
|
36
|
+
`_witchy-bnd4.xml`."
|
|
37
|
+
status: community
|
|
38
|
+
source: '`GetFolderXmlFilename` in WitchyBND/Parsers/WFolderParser.cs returns
|
|
39
|
+
`$"_witchy-{name}.xml"`; WitchyBND/Parsers/Binder/WPARAMBND4.cs calls it with "bnd4"; the
|
|
40
|
+
README shows the same pattern for other formats (`_witchy-anibnd4.xml`, `_witchy-tae.xml`)'
|
|
41
|
+
tags:
|
|
42
|
+
- witchybnd
|
|
43
|
+
- xml
|
|
44
|
+
- roundtrip
|
|
45
|
+
- convert
|
|
46
|
+
- sidecar
|
|
47
|
+
- text-converter
|
|
48
|
+
detail: "The sidecar is not cosmetic — it carries the binder's `<version>` element and, for a
|
|
49
|
+
regulation, the regulation version, and repack validates against them. That makes a deleted or
|
|
50
|
+
hand-edited sidecar a real failure mode and a good validator target: a staged binder directory
|
|
51
|
+
with no `_witchy-*.xml` cannot be repacked at all."
|
|
52
|
+
- id: eldenring.toolchain.witchybnd-handles-regulation-encryption-itself
|
|
53
|
+
claim: WitchyBND detects a regulation.bin by filename and routes it through a dedicated PARAMBND4
|
|
54
|
+
parser that decrypts on unpack and re-encrypts on repack, and it refuses to repack a
|
|
55
|
+
regulation whose version is newer than the newest paramdef it bundles. So encryption is not a
|
|
56
|
+
step the caller has to implement.
|
|
57
|
+
status: community
|
|
58
|
+
source: WitchyBND/Parsers/Binder/WPARAMBND4.cs detects a filename containing "regulation" and ending
|
|
59
|
+
".bin" and dispatches to the regulation decryptor/encryptor; WitchyBND's changelog for
|
|
60
|
+
v2.1.1.0 — "Repacking PARAMBND4 will now perform a dry PARAM unpack attempt on all constituent
|
|
61
|
+
PARAM files, to catch user errors attempting to pack outdated PARAMs into new regulation
|
|
62
|
+
versions" and "Repacking PARAMBND4 will now fail if the regulation version exceeds the latest
|
|
63
|
+
known regulation version in Paramdex"
|
|
64
|
+
tags:
|
|
65
|
+
- witchybnd
|
|
66
|
+
- regulation
|
|
67
|
+
- encryption
|
|
68
|
+
- paramdex
|
|
69
|
+
- version
|
|
70
|
+
- guard
|
|
71
|
+
detail: WitchyBND ships its own vendored Paramdex under WitchyBND/Assets/Paramdex/ER/ with Defs,
|
|
72
|
+
Names, Meta, Tdfs and an Upgrader/version.txt naming the newest regulation it knows. Reading
|
|
73
|
+
that file is a cheap, install-free way for `check_toolchain` to report which regulation
|
|
74
|
+
versions the installed WitchyBND can actually round-trip — a version axis no `--version` flag
|
|
75
|
+
exposes.
|
|
76
|
+
- id: eldenring.toolchain.dsmsportable-is-the-only-unattended-param-editor
|
|
77
|
+
claim: DSMSPortable is the one command-line tool that edits and merges Elden Ring params unattended.
|
|
78
|
+
It takes regulation.bin as its positional argument, defaults to Elden Ring, applies CSV or
|
|
79
|
+
mass-edit scripts, exports and diffs params, and has separate merge modes for FMG, TPF,
|
|
80
|
+
layout, HKS, EMEVD, BND and TAE files.
|
|
81
|
+
status: community
|
|
82
|
+
source: 'DSMSPortable/Program.cs usage output at https://github.com/mountlover/DSMSPortable —
|
|
83
|
+
"Usage: DSMSPortable [paramfile] [-G gametype] [-P gamepath] [-U oldvanillaparams] [-C2M ...]
|
|
84
|
+
[-R paramname:query ...] [-C csvfile ...] [-M[+] masseditfile ...] [-X paramname[:query] ...]
|
|
85
|
+
[-D diffparamfile] [-O outputpath]"; "paramfile — Path to regulation.bin file (or respective
|
|
86
|
+
param file for other FromSoft games) to modify"; "-G gametype ... The default is Elden Ring";
|
|
87
|
+
plus `--fmgentry`, `--fmgmerge`, `--layoutmerge`, `--texturemerge`, `--animerge`,
|
|
88
|
+
`--animdiff`, `--bndmerge`, `--bnddiff`, `--hksmerge`, `--emevdmerge`, `--emevddiff`'
|
|
89
|
+
tags:
|
|
90
|
+
- dsmsportable
|
|
91
|
+
- cli
|
|
92
|
+
- unattended
|
|
93
|
+
- merge
|
|
94
|
+
- massedit
|
|
95
|
+
- regulation
|
|
96
|
+
- build
|
|
97
|
+
detail: Its README is mostly a numbered exit-code table (0 success through 20 "Massedit parse
|
|
98
|
+
error", with a negative code for ".NET not installed"), which is exactly what a toolchain
|
|
99
|
+
adapter needs to classify a failure rather than just reporting non-zero. Program.cs carries
|
|
100
|
+
`VERSION = "1.9"`. Two cautions - it needs the .NET 6 Desktop Runtime, and it is unmaintained
|
|
101
|
+
and absent from the community wiki's tool database, so it is a viable but low-adoption
|
|
102
|
+
dependency rather than a safe default.
|
|
103
|
+
- id: eldenring.toolchain.every-other-editor-is-gui-only
|
|
104
|
+
claim: Smithbox, DSMapStudio, UXM Selective Unpack and DSAnimStudio are all GUI applications with no
|
|
105
|
+
documented command line. ModWright cannot drive any of them; it can only check what they
|
|
106
|
+
produced.
|
|
107
|
+
status: community
|
|
108
|
+
source: https://github.com/vawser/Smithbox README Usage section ("Once installed, click the
|
|
109
|
+
Smithbox.Vulkan.exe to launch the fully featured version of Smithbox") and its Requirements
|
|
110
|
+
section (a Vulkan 1.3 GPU); https://github.com/Nordgaren/UXM-Selective-Unpack README, which
|
|
111
|
+
describes only buttons ("The Unpack button will extract all files from the game archives,
|
|
112
|
+
unless you select files in the \"View Files\" menu"; "The Patch button will modify the
|
|
113
|
+
executable"; "the Restore button will restore the original executable and delete the extracted
|
|
114
|
+
files")
|
|
115
|
+
tags:
|
|
116
|
+
- smithbox
|
|
117
|
+
- dsmapstudio
|
|
118
|
+
- uxm
|
|
119
|
+
- dsanimstudio
|
|
120
|
+
- gui
|
|
121
|
+
- scope
|
|
122
|
+
- boundary
|
|
123
|
+
detail: This is the single biggest structural difference from the Cyberpunk and BG3 surfaces, where
|
|
124
|
+
WolvenKit CLI and divine cover most of the pipeline. Here the scriptable surface is exactly
|
|
125
|
+
two tools — WitchyBND and DSMSPortable — and everything else is a person at a keyboard. A
|
|
126
|
+
surface that claims otherwise will produce build steps that cannot run.
|
|
127
|
+
- id: eldenring.toolchain.souls-formats-is-a-library-not-a-cli
|
|
128
|
+
claim: SoulsFormats, the C# library every one of these tools is built on, ships no command-line
|
|
129
|
+
interface — it is a .NET library, GPL-3.0, and the original repository has been archived since
|
|
130
|
+
2025-05-26. The maintained continuation is soulsmods/SoulsFormatsNEXT, which is where Elden
|
|
131
|
+
Ring map support lives.
|
|
132
|
+
status: community
|
|
133
|
+
source: https://github.com/JKAnderson/SoulsFormats — archive banner dated May 26, 2025; README "A
|
|
134
|
+
.NET library for reading and writing various FromSoftware file formats, targeting .NET
|
|
135
|
+
Framework 4.6.2 and .NET Standard 2.1. Dark Souls, Demon's Souls, Bloodborne, and Sekiro are
|
|
136
|
+
the main focus, but other From games may be supported to varying degrees."; the repository's
|
|
137
|
+
top level is a solution and a library project with no console project
|
|
138
|
+
tags:
|
|
139
|
+
- soulsformats
|
|
140
|
+
- library
|
|
141
|
+
- license
|
|
142
|
+
- gpl
|
|
143
|
+
- archived
|
|
144
|
+
- soulsformatsnext
|
|
145
|
+
detail: The archived repository's MSB support stops at MSB1/2/3/B/D/N/S — there is no MSBE, so Elden
|
|
146
|
+
Ring map reading is not in it. SoulsFormatsNEXT adds Formats/MSB/MSBE/ and names Elden Ring in
|
|
147
|
+
its supported list. Both are GPL-3.0 libraries, so ModWright's only sound relationship with
|
|
148
|
+
either is to shell out to a tool that embeds them, the way it already shells out to divine and
|
|
149
|
+
WolvenKit CLI rather than linking them.
|
|
150
|
+
- id: eldenring.toolchain.uxm-patching-is-the-other-deploy-target-and-it-is-destructive
|
|
151
|
+
claim: The alternative to a loader overlay is UXM Selective Unpack, which extracts the archives to
|
|
152
|
+
loose files and patches eldenring.exe to read them. It is destructive and mutually exclusive
|
|
153
|
+
with online play, and unpacking without patching, or patching without unpacking, breaks the
|
|
154
|
+
game.
|
|
155
|
+
status: community
|
|
156
|
+
source: https://github.com/Nordgaren/UXM-Selective-Unpack README — "Enables file modding for DS1,
|
|
157
|
+
DS2, SotFS, DS3, Sekiro and Elden Ring by unpacking game archives and patching the executable
|
|
158
|
+
to load loose files instead."; "Patching the executable without also unpacking the archives
|
|
159
|
+
will crash the game, so make sure you do both."; and, under Elden Ring, "You cannot play
|
|
160
|
+
online with an modified exe, so you cannot go online with an unpacked game (Nor can you go
|
|
161
|
+
online with Mod Engine 2)"
|
|
162
|
+
tags:
|
|
163
|
+
- uxm
|
|
164
|
+
- unpack
|
|
165
|
+
- patch
|
|
166
|
+
- deploy
|
|
167
|
+
- destructive
|
|
168
|
+
- online
|
|
169
|
+
- restore
|
|
170
|
+
detail: There is a documented way back — "the Restore button will restore the original executable
|
|
171
|
+
and delete the extracted files" — which makes this reversible but not cheap. DSMapStudio's
|
|
172
|
+
README requires this path for Elden Ring ("Use UXM Selective Unpack to extract the game
|
|
173
|
+
files... at least the map, asset, chr, and msg directories are needed for basic editor
|
|
174
|
+
usage"), whereas Smithbox says "You no longer need to unpack a game for any of the editors"
|
|
175
|
+
and points at Nuxe if you do. A deploy target this coarse is a poor default; the loader
|
|
176
|
+
overlay should be the primary one.
|
|
177
|
+
- id: eldenring.toolchain.dsmsportable-exit-code-table
|
|
178
|
+
claim: "DSMSPortable's exit codes are documented in full: below 0 \".NET not installed\", 1
|
|
179
|
+
Unhandled Exception, 2 Unhandled Exception processing arguments, 3 No gamepath specified, 4
|
|
180
|
+
Could not resolve output path, 5 Unrecognized argument switch, 6 Failed to read TAE file, 7
|
|
181
|
+
Timed out loading param files, 8 Failed to save/overwrite file, 9 Failed to save param file,
|
|
182
|
+
10 Failed to generate temporary files, 11 Invalid FMG file specified, 12 XML parsing error, 13
|
|
183
|
+
Invalid in-line FMG entry, 14 Invalid sblytbnd file specified, 15 Invalid TPF file specified,
|
|
184
|
+
16 Invalid BND file specified, 17 Invalid HKS/Lua file specified, 18 Invalid msgbnd file
|
|
185
|
+
specified, 19 Invalid anibnd file specified, 20 Massedit parse error."
|
|
186
|
+
status: community
|
|
187
|
+
source: https://github.com/mountlover/DSMSPortable README.md, "DSMSPortable Error Codes" (read
|
|
188
|
+
2026-09-11), and its Requirements section naming the .NET 6.0 Desktop Runtime
|
|
189
|
+
tags:
|
|
190
|
+
- dsmsportable
|
|
191
|
+
- exit-code
|
|
192
|
+
- cli
|
|
193
|
+
- toolchain
|
|
194
|
+
- adapter
|
|
195
|
+
- dotnet
|
|
196
|
+
detail: '`src/surfaces/eldenring/tools.ts` carries the table as DSMSPORTABLE_EXIT_CODES with
|
|
197
|
+
`explainDsmsPortableExit`, so a build step can say "No gamepath specified" rather than "exit
|
|
198
|
+
3". A negative code on a fresh machine means the runtime, not the arguments.'
|
|
199
|
+
related:
|
|
200
|
+
- eldenring.toolchain.dsmsportable-is-the-only-unattended-param-editor
|
|
201
|
+
- id: eldenring.toolchain.witchybnd-version-flag-prints-the-assembly-version
|
|
202
|
+
claim: "`WitchyBND -v` (also `--version`) prints `WitchyBND v<assembly version>`, e.g. `WitchyBND
|
|
203
|
+
v3.0.1.0`, four components from the .NET assembly rather than the release tag."
|
|
204
|
+
status: community
|
|
205
|
+
source: WitchyBND/Program.cs — `if (opt.Version) ... _output.WriteLine($"{assembly.GetName().Name}
|
|
206
|
+
v{assembly.GetName().Version.ToString()}"`; Configuration.cs `[Option('v', "version", HelpText
|
|
207
|
+
= "Display version information.")]`
|
|
208
|
+
tags:
|
|
209
|
+
- witchybnd
|
|
210
|
+
- version
|
|
211
|
+
- cli
|
|
212
|
+
- toolchain
|
|
213
|
+
- flag
|
|
214
|
+
detail: The toolchain spec `witchybnd` probes with `-v` and matches the printed `WitchyBND v` prefix
|
|
215
|
+
followed by the dotted number; the regulation-version axis
|
|
216
|
+
(Assets/Paramdex/ER/Upgrader/version.txt) is a different number and is read separately.
|
|
217
|
+
related:
|
|
218
|
+
- eldenring.toolchain.witchybnd-has-a-real-headless-mode
|
|
219
|
+
- id: eldenring.toolchain.witchybnd-sidecar-shape
|
|
220
|
+
claim: WitchyBND unpacks a binder into a folder named after the file with its dots replaced by
|
|
221
|
+
dashes (`c0000.anibnd.dcx` becomes `c0000-anibnd-dcx`; a name with no dot gains `-unpacked`)
|
|
222
|
+
and writes `_witchy-<tag>.xml` inside it, `<bnd4>` for a BND4 with `<version>`, `<format>`,
|
|
223
|
+
`<bigendian>`, `<bitbigendian>`, `<unicode>`, `<extended>`, `<unk04>`, `<unk05>`, an optional
|
|
224
|
+
`<root>` (the common path prefix it stripped) and `<compression>`, then `<files>` of `<file>`
|
|
225
|
+
elements each carrying `<flags>`, `<id>`, `<path>` and, when two entries share a path, a
|
|
226
|
+
`<suffix>` such as ` (2)` that the on-disk file carries before its extension. Alongside those
|
|
227
|
+
the manifest carries `<filename>` (and `<sourcePath>` when unpacked recursively), which is
|
|
228
|
+
where repack writes the rebuilt binder. Repack reads `<version>` and `<filename>`
|
|
229
|
+
unconditionally and stops with "File not found" on any entry missing from the folder; files
|
|
230
|
+
not named in the sidecar are not packed.
|
|
231
|
+
status: community
|
|
232
|
+
source: WitchyBND/Parsers/WFolderParser.cs `GetUnpackDestPath` (`fileName.Replace('.', '-')`,
|
|
233
|
+
`-unpacked`), `GetFolderXmlFilename` (`$"_witchy-{name}.xml"`), `IsUnpacked` (the root tag
|
|
234
|
+
check), `GetRepackDestPath` ("XML does not have filename."); WitchyBND/Parsers/WParser.cs
|
|
235
|
+
`PrepareXmlManifest` and `AddLocationToXml` (`<compression>`, `<filename>`, `<sourcePath>`,
|
|
236
|
+
`<root>`); WitchyBND/Parsers/Binder/WBND4.cs `Unpack` (the element list) and `Repack`
|
|
237
|
+
(`xml.Element("version")!.Value`); WitchyBND/Parsers/WBinderParser.cs `WriteBinderFiles`
|
|
238
|
+
(`<file>` with flags, id, path, suffix) and `ReadBinderFiles` (`OSPath.Combine(srcDirPath,
|
|
239
|
+
dir, stem + suffix + ext)`, `File not found`)
|
|
240
|
+
tags:
|
|
241
|
+
- witchybnd
|
|
242
|
+
- sidecar
|
|
243
|
+
- xml
|
|
244
|
+
- unpack
|
|
245
|
+
- repack
|
|
246
|
+
- naming
|
|
247
|
+
- validator
|
|
248
|
+
detail: This is what `eldenring.binders.sidecar-entries` and `eldenring.binders.unpacked-in-package`
|
|
249
|
+
rest on. The folder-name test for "looks like an unpack folder" is a heuristic on that naming;
|
|
250
|
+
the sidecar's presence is the real evidence, and the rule says which of the two it saw. "Packs
|
|
251
|
+
only what the sidecar names" holds for the plain binder parsers (`bnd4`, `bnd3`, `bxf4`,
|
|
252
|
+
`bxf3`); WitchyBND's special modes write their own tag and folder suffix
|
|
253
|
+
(`_witchy-anibnd4.xml` in a `-wanibnd` folder) and repack the animation files they find by
|
|
254
|
+
scanning it, so the stray-file check is scoped to the four plain tags.
|
|
255
|
+
related:
|
|
256
|
+
- eldenring.toolchain.witchybnd-xml-is-the-text-converter
|
|
@@ -0,0 +1,157 @@
|
|
|
1
|
+
game: nivalisnights
|
|
2
|
+
topic: modding.runtime
|
|
3
|
+
title: Nivalis Nights modding at runtime — BepInEx 6 IL2CPP, the studio's developer mode, saves and
|
|
4
|
+
sidecars, and decoding the build's assets
|
|
5
|
+
facts:
|
|
6
|
+
- id: nivalisnights.modding.runtime.bepinex-be788-il2cpp-loads-plugins
|
|
7
|
+
claim: "BepInEx 6 bleeding-edge #788 in its Unity.IL2CPP build loads plugins on Nivalis Nights: a
|
|
8
|
+
net6.0 `BasePlugin` compiled against `BepInEx/core` and the generated `BepInEx/interop` loads,
|
|
9
|
+
and its HarmonyX patches on game methods fire."
|
|
10
|
+
status: verified
|
|
11
|
+
verified_on: "25680465"
|
|
12
|
+
source: ModWright field verification
|
|
13
|
+
tags:
|
|
14
|
+
- bepinex
|
|
15
|
+
- il2cpp
|
|
16
|
+
- loader
|
|
17
|
+
- harmony
|
|
18
|
+
- interop
|
|
19
|
+
- plugins
|
|
20
|
+
detail: The first launch after installing downloaded the Unity base libraries from
|
|
21
|
+
unity.bepinex.dev, ran Cpp2IL and generated 125 interop assemblies in about 25 s at a black
|
|
22
|
+
screen, so it needs network access. Patches on GameSceneManager.LoadArea and the
|
|
23
|
+
PlayerInventory.Money setter fired. The installed .NET 8 SDK built the net6.0 plugin after
|
|
24
|
+
fetching the 6.0.36 reference pack.
|
|
25
|
+
- id: nivalisnights.modding.runtime.devmode-postfix-opens-developer-options
|
|
26
|
+
claim: A Harmony postfix forcing `Nivalis.DevOptions.DevMode.IsDevMode` to true, applied in the
|
|
27
|
+
plugin's `Load()`, populates the studio's Developer Options catalogue, and
|
|
28
|
+
`DevOptionMenuRevised.Instance.Open()` shows its window from the main menu. Esc closes it.
|
|
29
|
+
status: verified
|
|
30
|
+
verified_on: "25680465"
|
|
31
|
+
source: ModWright field verification
|
|
32
|
+
tags:
|
|
33
|
+
- devmode
|
|
34
|
+
- developer-options
|
|
35
|
+
- harmony
|
|
36
|
+
- bridge
|
|
37
|
+
- cheats
|
|
38
|
+
detail: The catalogue held 58 options on this build (55 on 25603526). The probe read their display
|
|
39
|
+
names and shortcuts at runtime from DevOptionMenuRevised._methodDisplayString, e.g. F3 'Toggle
|
|
40
|
+
UI Shown' and F11 'Toggle No Clip'. The postfix must be in place before the _Global scene's UI
|
|
41
|
+
loads, because the menu's Awake builds the catalogue once. Opening through Instance.Open()
|
|
42
|
+
bypasses the Ctrl+Shift+F12 hotkey and the BuildDeveloperOptionsEnabled asset flag.
|
|
43
|
+
- id: nivalisnights.modding.runtime.isdevmode-log-line-precedes-postfix
|
|
44
|
+
claim: "`Player.log` prints `isDevMode:False` even while a plugin's postfix has forced developer
|
|
45
|
+
mode on, because the game logs inside the getter before the postfix changes the return value;
|
|
46
|
+
that line is no evidence the force failed."
|
|
47
|
+
status: verified
|
|
48
|
+
verified_on: "25680465"
|
|
49
|
+
source: ModWright field verification
|
|
50
|
+
tags:
|
|
51
|
+
- devmode
|
|
52
|
+
- logs
|
|
53
|
+
- triage
|
|
54
|
+
- player-log
|
|
55
|
+
- id: nivalisnights.modding.runtime.articy-script-runner-returns-run-success
|
|
56
|
+
claim: "`Nivalis.Dialogue.ArticyScriptRunner.DoArticyScript(string)` returns whether the script ran,
|
|
57
|
+
not the expression's value. To read a story variable, use
|
|
58
|
+
`ArticyDatabase.DefaultGlobalVariables.Variables`, a name-to-value dictionary."
|
|
59
|
+
status: verified
|
|
60
|
+
verified_on: "25680465"
|
|
61
|
+
source: ModWright field verification
|
|
62
|
+
tags:
|
|
63
|
+
- articy
|
|
64
|
+
- story-variables
|
|
65
|
+
- bridge
|
|
66
|
+
- scripting
|
|
67
|
+
detail: "'Ava.ControlRoomUnlocked == false' returned True while the variable read True, and the
|
|
68
|
+
variable was unchanged afterwards. The dictionary held 1,822 variables on this build."
|
|
69
|
+
- id: nivalisnights.modding.runtime.save-sidecar-round-trip
|
|
70
|
+
claim: "A plugin can keep its own state beside a save: a file written from a
|
|
71
|
+
`SerializationManager.Save(string, bool)` postfix as
|
|
72
|
+
`<persistentDataPath>/<saveName>.modwright.json` and read back from a
|
|
73
|
+
`SerializationManager.Load(string)` prefix survives a save and reload, with no errors from the
|
|
74
|
+
game's save loader."
|
|
75
|
+
status: verified
|
|
76
|
+
verified_on: "25680465"
|
|
77
|
+
source: ModWright field verification
|
|
78
|
+
tags:
|
|
79
|
+
- saves
|
|
80
|
+
- sidecar
|
|
81
|
+
- persistence
|
|
82
|
+
- mod-state
|
|
83
|
+
related:
|
|
84
|
+
- id: nivalisnights.modding.runtime.save-loader-cannot-skip-unknown-packet
|
|
85
|
+
detail: the reason mod state belongs in a sidecar and never in a new save packet
|
|
86
|
+
- id: nivalisnights.modding.runtime.steam-cloud-syncs-only-sav-and-png
|
|
87
|
+
claim: Steam Auto-Cloud for Nivalis Nights tracks only `.sav` and `.png` files in the save folder,
|
|
88
|
+
so a mod's sidecar file next to a save stays on the machine and does not follow the player to
|
|
89
|
+
another PC.
|
|
90
|
+
status: verified
|
|
91
|
+
verified_on: "25680465"
|
|
92
|
+
source: ModWright field verification
|
|
93
|
+
tags:
|
|
94
|
+
- saves
|
|
95
|
+
- steam-cloud
|
|
96
|
+
- sidecar
|
|
97
|
+
- id: nivalisnights.modding.runtime.save-loader-cannot-skip-unknown-packet
|
|
98
|
+
claim: The save loader (`ManagersSave.Load`) cannot skip a manager packet it does not recognise. It
|
|
99
|
+
logs `No packet found for guid <id>` and reads on from the wrong place, so a mod must never
|
|
100
|
+
add a save packet.
|
|
101
|
+
status: inferred
|
|
102
|
+
source: ModWright research
|
|
103
|
+
tags:
|
|
104
|
+
- saves
|
|
105
|
+
- packets
|
|
106
|
+
- compatibility
|
|
107
|
+
- uninstall
|
|
108
|
+
detail: "Packets carry a length-prefixed id and no length field, so the bytes after an unknown id
|
|
109
|
+
cannot be stepped over. Ghost blocks are different: they carry int64 absolute end offsets and
|
|
110
|
+
an unknown prefab is skipped. This was read from code; no save with an unknown packet has been
|
|
111
|
+
loaded."
|
|
112
|
+
- id: nivalisnights.modding.runtime.stripped-typetrees-decode-with-attribute-dummy-dlls
|
|
113
|
+
claim: The build's MonoBehaviour and ScriptableObject fields decode with UnityPy only through type
|
|
114
|
+
trees generated from Cpp2IL dummy DLLs made with `--use-processor
|
|
115
|
+
attributeanalyzer,attributeinjector`. TypeTreeGeneratorAPI's own IL2CPP loader fails on this
|
|
116
|
+
build, and the generated base nodes put `m_Script` 3 bytes off.
|
|
117
|
+
status: inferred
|
|
118
|
+
source: ModWright research
|
|
119
|
+
tags:
|
|
120
|
+
- index
|
|
121
|
+
- unitypy
|
|
122
|
+
- cpp2il
|
|
123
|
+
- typetrees
|
|
124
|
+
- il2cpp
|
|
125
|
+
detail: "Measured by the index build rather than observed in the engine. load_il2cpp fails with
|
|
126
|
+
'Sequence contains no matching element'. Without the attribute processors, private
|
|
127
|
+
[SerializeField] fields are missing. m_Script is read from the raw bytes instead: FileID int32
|
|
128
|
+
at 16, PathID int64 at 20. On build 25680465 every definition in the default folders decoded,
|
|
129
|
+
including the 1,589 NPCs reached through PeopleDatabase."
|
|
130
|
+
- id: nivalisnights.modding.runtime.serializereference-folders-do-not-decode
|
|
131
|
+
claim: The `quests`, `skills`, `ghosts` and `backgroundnpcconversations` Resources folders do not
|
|
132
|
+
decode through generated type trees. Their `[SerializeReference]` polymorphic fields either
|
|
133
|
+
fail ('Failed to get ref type node') or make the generator run away.
|
|
134
|
+
status: inferred
|
|
135
|
+
source: ModWright research
|
|
136
|
+
tags:
|
|
137
|
+
- index
|
|
138
|
+
- serializereference
|
|
139
|
+
- quests
|
|
140
|
+
- skills
|
|
141
|
+
- unitypy
|
|
142
|
+
detail: The quests decode passed 12 GB of memory before it was killed. newsarticles fail
|
|
143
|
+
differently, with a consistent 44-byte shortfall. The index lists all five as not indexed,
|
|
144
|
+
with these reasons.
|
|
145
|
+
- id: nivalisnights.modding.runtime.bepinex6-chainloader-wording
|
|
146
|
+
claim: BepInEx 6's chainloader words its lines differently from BepInEx 5. It writes `1 plugin to
|
|
147
|
+
load`, not `1 plugin(s) to load`, and `Error loading [x]:` with no space before the colon. It
|
|
148
|
+
also reworded both dependency errors. BepInEx 5 log patterns miss these lines.
|
|
149
|
+
status: inferred
|
|
150
|
+
source: BepInEx at 5b766a3, BepInEx.Core/Bootstrap/BaseChainloader.cs;
|
|
151
|
+
test/fixtures/logs/nivalisnights/real/LogOutput.head.log
|
|
152
|
+
tags:
|
|
153
|
+
- bepinex
|
|
154
|
+
- logs
|
|
155
|
+
- triage
|
|
156
|
+
- signatures
|
|
157
|
+
detail: The banner, plugin count and roll-call lines also match the real log from the field run.
|
|
@@ -0,0 +1,212 @@
|
|
|
1
|
+
game: skyrimse
|
|
2
|
+
topic: archives.bsa
|
|
3
|
+
title: BSA archives — the v105 format, and how an archive gets loaded at all
|
|
4
|
+
facts:
|
|
5
|
+
- id: sse.archives.bsa.version-105
|
|
6
|
+
claim: Skyrim Special Edition uses BSA version 105 (0x69). Skyrim LE uses 104 (0x68) and Oblivion
|
|
7
|
+
103 (0x67). The version field is a uint32 at offset 4 of a 36-byte header that begins with the
|
|
8
|
+
literal "BSA\0".
|
|
9
|
+
status: community
|
|
10
|
+
source: en.uesp.net "Skyrim Mod:Archive File Format", the intro and the Header table's version row
|
|
11
|
+
("Currently 104 (0x68) for Skyrim or 105 (0x69) for Skyrim Special Edition"); the same mapping
|
|
12
|
+
appears in Ryan-rsm-McKenzie/bsa include/bsa/tes4.hpp
|
|
13
|
+
tags:
|
|
14
|
+
- bsa
|
|
15
|
+
- archive
|
|
16
|
+
- version
|
|
17
|
+
- byte-layout
|
|
18
|
+
- parser
|
|
19
|
+
detail: UESP's stated reason for the split - "Bethesda serializes structs directly, including
|
|
20
|
+
undefined padding bits" - explains why the difference is purely in the folder record's
|
|
21
|
+
padding.
|
|
22
|
+
- id: sse.archives.bsa.v105-uses-lz4
|
|
23
|
+
claim: A compressed file block in a v105 (Skyrim SE) archive is a uint32 original size followed by
|
|
24
|
+
LZ4-compressed data. v104 (Skyrim LE) uses zlib for the same block.
|
|
25
|
+
status: community
|
|
26
|
+
source: en.uesp.net "Skyrim Mod:Archive File Format", section "Compressed File block" ("File data
|
|
27
|
+
that has been compressed with zlib (v104) or LZ4 (v105)"); Ryan-rsm-McKenzie/bsa
|
|
28
|
+
include/bsa/tes4.hpp ("The v105 format uses lz4")
|
|
29
|
+
tags:
|
|
30
|
+
- bsa
|
|
31
|
+
- archive
|
|
32
|
+
- compression
|
|
33
|
+
- lz4
|
|
34
|
+
- zlib
|
|
35
|
+
- parser
|
|
36
|
+
- id: sse.archives.bsa.folder-record-is-24-bytes-in-v105
|
|
37
|
+
claim: The v104 to v105 structural difference is the folder record. v104's is 16 bytes (8-byte name
|
|
38
|
+
hash, uint32 count, uint32 offset); v105's is 24, inserting a uint32 padding after count and
|
|
39
|
+
another after offset. The folder offset needs totalFileNameLength subtracted to become a real
|
|
40
|
+
file offset.
|
|
41
|
+
status: community
|
|
42
|
+
source: en.uesp.net "Skyrim Mod:Archive File Format", section "Folder Record"
|
|
43
|
+
tags:
|
|
44
|
+
- bsa
|
|
45
|
+
- archive
|
|
46
|
+
- byte-layout
|
|
47
|
+
- parser
|
|
48
|
+
- v104-vs-v105
|
|
49
|
+
detail: The file record stays 16 bytes in both (8-byte hash, uint32 size, uint32 offset). Folders
|
|
50
|
+
and files must be sorted by their 64-bit hash values.
|
|
51
|
+
- id: sse.archives.bsa.compressed-flag-means-default-not-all
|
|
52
|
+
claim: Archive flag 0x4 ("Compressed Archive") does not mean every file is compressed; it means
|
|
53
|
+
files are compressed by default. Bit 30 (0x40000000) of a file record's size field inverts
|
|
54
|
+
that default for the individual file.
|
|
55
|
+
status: community
|
|
56
|
+
source: en.uesp.net "Skyrim Mod:Archive File Format", the archiveFlags table ("This does not mean
|
|
57
|
+
all files are compressed. It means they are compressed by default") and the File Record
|
|
58
|
+
section
|
|
59
|
+
tags:
|
|
60
|
+
- bsa
|
|
61
|
+
- archive
|
|
62
|
+
- compression
|
|
63
|
+
- flags
|
|
64
|
+
- parser
|
|
65
|
+
- gotcha
|
|
66
|
+
detail: A reader that assumes the archive flag applies uniformly will decompress uncompressed data
|
|
67
|
+
on any archive with mixed content.
|
|
68
|
+
- id: sse.archives.bsa.directory-and-file-name-flags-are-required
|
|
69
|
+
claim: Archive flags 0x1 (Include Directory Names) and 0x2 (Include File Names) are set in every
|
|
70
|
+
official BSA, and UESP notes for each that the game may not load a BSA without the bit set.
|
|
71
|
+
status: community
|
|
72
|
+
source: en.uesp.net "Skyrim Mod:Archive File Format", archiveFlags table, bits 1 and 2
|
|
73
|
+
tags:
|
|
74
|
+
- bsa
|
|
75
|
+
- archive
|
|
76
|
+
- flags
|
|
77
|
+
- validation
|
|
78
|
+
detail: Other archiveFlags of note - 0x40 Xbox360 (all numbers and hashes big-endian), 0x100 Embed
|
|
79
|
+
File Names, 0x200 XMem codec (Xbox 360 only, requires 0x4). fileFlags is a separate
|
|
80
|
+
content-type mask - 0x1 Meshes, 0x2 Textures, 0x4 Menus, 0x8 Sounds, 0x10 Voices, 0x20
|
|
81
|
+
Shaders, 0x40 Trees, 0x80 Fonts, 0x100 Miscellaneous.
|
|
82
|
+
- id: sse.archives.bsa.two-ini-keys-under-archive-section
|
|
83
|
+
claim: The archive list lives in skyrim.ini under the [Archive] section in TWO keys,
|
|
84
|
+
SResourceArchiveList and SResourceArchiveList2. The second exists because the value is capped
|
|
85
|
+
- a joined list longer than 255 characters is split at the last comma before position 256.
|
|
86
|
+
status: community
|
|
87
|
+
source: ModOrganizer2/modorganizer-game_skyrimse src/skyrimsedataarchives.cpp
|
|
88
|
+
(SkyrimSEDataArchives::archives reads both keys; writeArchiveList performs the split);
|
|
89
|
+
modorganizer-game_gamebryo src/gamebryo/gamebryodataarchives.cpp getArchivesFromKey, which
|
|
90
|
+
passes the literal section name L"Archive" to GetPrivateProfileStringW
|
|
91
|
+
tags:
|
|
92
|
+
- bsa
|
|
93
|
+
- archive
|
|
94
|
+
- ini
|
|
95
|
+
- skyrim-ini
|
|
96
|
+
- sresourcearchivelist
|
|
97
|
+
- gotcha
|
|
98
|
+
detail: Reading only the first key silently misses every archive in a long list's tail. MO2 reads
|
|
99
|
+
skyrim.ini from the profile directory when profile-specific INI files are enabled, and from
|
|
100
|
+
Documents\My Games\<name> otherwise.
|
|
101
|
+
- id: sse.archives.bsa.seventeen-vanilla-archives
|
|
102
|
+
claim: Skyrim SE ships seventeen vanilla archives - Skyrim - Textures0 through Textures8, Meshes0
|
|
103
|
+
and Meshes1, Voices_en0, Sounds, Interface, Animations, Shaders and Misc.
|
|
104
|
+
status: community
|
|
105
|
+
source: ModOrganizer2/modorganizer-game_skyrimse src/skyrimsedataarchives.cpp,
|
|
106
|
+
SkyrimSEDataArchives::vanillaArchives
|
|
107
|
+
tags:
|
|
108
|
+
- bsa
|
|
109
|
+
- archive
|
|
110
|
+
- vanilla
|
|
111
|
+
- inventory
|
|
112
|
+
- id: sse.archives.bsa.bsarch-is-part-of-xedit
|
|
113
|
+
claim: BSArch, the command-line BSA packer, lives inside the xEdit repository at Tools/BSArchive and
|
|
114
|
+
is what xEdit itself uses - xEdit's own .bsa/.ba2 code was replaced by BSArch's.
|
|
115
|
+
status: community
|
|
116
|
+
source: github.com/TES5Edit/TES5Edit Tools/BSArchive/bsarch.dpr (program bsarch; {$APPTYPE CONSOLE}
|
|
117
|
+
sVersion = '0.7', MPL 1.1); whatsnew.md ("xEdit specific code for .bsa/.ba2 has been
|
|
118
|
+
completely replaced with the code from BSArch")
|
|
119
|
+
tags:
|
|
120
|
+
- bsa
|
|
121
|
+
- bsarch
|
|
122
|
+
- toolchain
|
|
123
|
+
- xedit
|
|
124
|
+
- packing
|
|
125
|
+
- id: sse.archives.bsa.bsarch-pack-syntax
|
|
126
|
+
claim: BSArch packs a Skyrim SE archive with `bsarch pack <folder> <archive.bsa> -sse [-z] [-share]
|
|
127
|
+
[-mt]`, where -sse selects the v105 format, -z compresses, -share deduplicates
|
|
128
|
+
binary-identical files and -mt runs multi-threaded.
|
|
129
|
+
status: community
|
|
130
|
+
source: github.com/TES5Edit/TES5Edit Tools/BSArchive/bsarch.dpr, the help text, whose SSE example is
|
|
131
|
+
`bsarch pack "d:\my mod\data" "d:\my mod\data\new.bsa" -sse -z`
|
|
132
|
+
tags:
|
|
133
|
+
- bsa
|
|
134
|
+
- bsarch
|
|
135
|
+
- cli
|
|
136
|
+
- packing
|
|
137
|
+
- build-step
|
|
138
|
+
- toolchain
|
|
139
|
+
detail: The -af and -ff flag overrides apply to "Oblivion, Fallout 3/NV and Skyrim LE archives
|
|
140
|
+
only". BSArch's exit code is 1 only on an unhandled exception - there are no granular codes.
|
|
141
|
+
- id: sse.archives.bsa.compressed-archives-break-sound
|
|
142
|
+
claim: Sounds and voices do not work in compressed archives in any Bethesda game. A single sound or
|
|
143
|
+
voice file among thousands forces the whole archive to be uncompressed.
|
|
144
|
+
status: community
|
|
145
|
+
source: github.com/TES5Edit/TES5Edit Tools/BSArchive/bsarch.dpr, the -z parameter's help text ("Keep
|
|
146
|
+
in mind that sounds and voices don't work in compressed archives in all Bethesda games! Even
|
|
147
|
+
if your archive contains a single sound/voice file out of thousands, it must be
|
|
148
|
+
uncompressed.")
|
|
149
|
+
tags:
|
|
150
|
+
- bsa
|
|
151
|
+
- compression
|
|
152
|
+
- audio
|
|
153
|
+
- gotcha
|
|
154
|
+
- build-step
|
|
155
|
+
- validator
|
|
156
|
+
detail: A build step that packs with -z should refuse, or warn, when the staged tree contains
|
|
157
|
+
anything under sound/ or a .fuz/.xwm/.wav file. The symptom in game is silence, not an error.
|
|
158
|
+
- id: sse.archives.bsa.file-record-blocks-and-name-block
|
|
159
|
+
claim: "After the folder records come the file record blocks, one per folder in folder-record order:
|
|
160
|
+
a bzstring folder name (a length byte, the lower-case backslash-separated name, a terminating
|
|
161
|
+
\\0) when archive flag 0x1 is set, then that folder's 16-byte file records (8-byte name hash,
|
|
162
|
+
uint32 size, uint32 offset from the start of the file). Then, when flag 0x2 is set, the file
|
|
163
|
+
name block: every file's lower-case name with no path, \\0-terminated, in the same order as
|
|
164
|
+
the records. The folder record's offset field is the block's offset plus totalFileNameLength."
|
|
165
|
+
status: community
|
|
166
|
+
source: en.uesp.net "Skyrim Mod:Archive File Format" (read 2026-09-11), sections "File Record
|
|
167
|
+
blocks" ("name | bzstring | Name of the folder. Only present if Bit 1 of archiveFlags is
|
|
168
|
+
set."), "File Record" ("offset ... is offset from file byte zero (start), NOT from this
|
|
169
|
+
location"), "File Name block" ("If archive flag 0x2 is not set, this block is omitted. A block
|
|
170
|
+
of lower case file names, one after another, each ending in a \0. They are ordered in the same
|
|
171
|
+
order as those generated with the file folder block contents"), and "Folder Record" ("Subtract
|
|
172
|
+
totalFileNameLength to get the actual offset within the file.")
|
|
173
|
+
tags:
|
|
174
|
+
- bsa
|
|
175
|
+
- archive
|
|
176
|
+
- byte-layout
|
|
177
|
+
- parser
|
|
178
|
+
- names
|
|
179
|
+
detail: With both name flags set (every official archive), the whole table is a deterministic length
|
|
180
|
+
from the header alone (header, folder records, the folder names plus one length byte each, the
|
|
181
|
+
file records, the file names), so a reader can fetch exactly the table and never the payloads.
|
|
182
|
+
The page was readable on 2026-09-11 without the Cloudflare challenge met earlier in ModWright
|
|
183
|
+
research; the same-base-name loading rule is still not on it.
|
|
184
|
+
- id: sse.archives.bsa.name-hash-algorithm
|
|
185
|
+
claim: "A record's 64-bit hash is the Tes4/Tes5 pair: the name lower-cased with forward slashes made
|
|
186
|
+
backslashes; for a file, split at the last dot into root and extension. The low 32 bits are
|
|
187
|
+
(last root char) | (second-last root char << 8, when the root is longer than two) | (root
|
|
188
|
+
length << 16) | (first root char << 24), with 0x80 (.kf), 0x8000 (.nif), 0x8080 (.dds) or
|
|
189
|
+
0x80000000 (.wav) set on top for those four extensions. The high 32 bits are the sum of two
|
|
190
|
+
folds with multiplier 0x1003f: over the root's characters from the second to the third-last,
|
|
191
|
+
and over the extension including its dot. A folder hashes whole, with no extension split and
|
|
192
|
+
no leading or trailing slash."
|
|
193
|
+
status: community
|
|
194
|
+
source: "en.uesp.net \"Oblivion Mod:Hash Calculation\" (read 2026-09-11): the Overview (\"The hash
|
|
195
|
+
cannot be calculated using / (forward slashes) or upper case characters ... Folder hash values
|
|
196
|
+
must not include leading or trailing slashes ... The extension must include the '.'\") and its
|
|
197
|
+
Python and C implementations, which agree on these four extensions; the transcription follows
|
|
198
|
+
the Python, which compares the whole extension string, rather than the C, which loads four
|
|
199
|
+
bytes at the dot and so would also set the bit for a longer extension beginning \".nif\",
|
|
200
|
+
\".dds\" or \".wav\"; the reference Python was run to produce the test vectors in
|
|
201
|
+
test/unit/skyrimse/archive-records.test.ts"
|
|
202
|
+
tags:
|
|
203
|
+
- bsa
|
|
204
|
+
- archive
|
|
205
|
+
- hash
|
|
206
|
+
- parser
|
|
207
|
+
- validator
|
|
208
|
+
detail: "This is what lets a validator check every record's hash against the name the archive
|
|
209
|
+
carries for it, with no game: a hash that is not its name's (a tool that hashed a
|
|
210
|
+
differently-cased or slash-separated name) leaves the entry unreachable by name. UESP's
|
|
211
|
+
\"Files and Dirs order\" section adds that folders and files must be sorted by these hash
|
|
212
|
+
values."
|