universal-game-modder 0.1.4
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/ACCEPTABLE_USE.md +49 -0
- package/CHANGELOG.md +119 -0
- package/LICENSE +21 -0
- package/LICENSE-EULA.md +62 -0
- package/README.md +162 -0
- package/VERIFICATION.md +132 -0
- package/dist/backends/child-pool.js +91 -0
- package/dist/backends/mcp-child.js +102 -0
- package/dist/backends/mcp-child.js.map +1 -0
- package/dist/core/config.d.ts +10 -0
- package/dist/core/config.js +48 -0
- package/dist/core/config.js.map +1 -0
- package/dist/core/engine-detector.d.ts +13 -0
- package/dist/core/engine-detector.js +247 -0
- package/dist/core/engine-detector.js.map +1 -0
- package/dist/core/event-bus.js +18 -0
- package/dist/core/file-classifier.js +394 -0
- package/dist/core/model-db.js +517 -0
- package/dist/core/model-db.js.map +1 -0
- package/dist/core/router.d.ts +6 -0
- package/dist/core/router.js +143 -0
- package/dist/core/router.js.map +1 -0
- package/dist/core/session.js +114 -0
- package/dist/decoders/audio-export.js +57 -0
- package/dist/decoders/mesh-export.d.ts +20 -0
- package/dist/decoders/mesh-export.js +174 -0
- package/dist/decoders/mesh-export.js.map +1 -0
- package/dist/decoders/native/disassembler.js +85 -0
- package/dist/decoders/native/disassembler.js.map +1 -0
- package/dist/decoders/png-encode.d.ts +17 -0
- package/dist/decoders/png-encode.js +33 -0
- package/dist/decoders/texture-decode.js +278 -0
- package/dist/decoders/texture-decode.js.map +1 -0
- package/dist/decoders/unity/audioclip.d.ts +55 -0
- package/dist/decoders/unity/audioclip.js +87 -0
- package/dist/decoders/unity/audioclip.js.map +1 -0
- package/dist/decoders/unity/binary-reader.d.ts +45 -0
- package/dist/decoders/unity/binary-reader.js +141 -0
- package/dist/decoders/unity/binary-reader.js.map +1 -0
- package/dist/decoders/unity/mesh.js +198 -0
- package/dist/decoders/unity/mesh.js.map +1 -0
- package/dist/decoders/unity/ress-reader.d.ts +33 -0
- package/dist/decoders/unity/ress-reader.js +82 -0
- package/dist/decoders/unity/ress-reader.js.map +1 -0
- package/dist/decoders/unity/serialized-file.d.ts +65 -0
- package/dist/decoders/unity/serialized-file.js +144 -0
- package/dist/decoders/unity/texture2d.js +185 -0
- package/dist/decoders/unity/vertex-data.d.ts +54 -0
- package/dist/decoders/unity/vertex-data.js +174 -0
- package/dist/decoders/unity/vertex-data.js.map +1 -0
- package/dist/index.d.ts +1 -0
- package/dist/index.js +23 -0
- package/dist/server.d.ts +1 -0
- package/dist/server.js +66 -0
- package/dist/tools/decode-tools.d.ts +29 -0
- package/dist/tools/decode-tools.js +441 -0
- package/dist/tools/delegates/jar-editor.d.ts +2 -0
- package/dist/tools/delegates/jar-editor.js +276 -0
- package/dist/tools/delegates/unity-decompiler.d.ts +2 -0
- package/dist/tools/delegates/unity-decompiler.js +291 -0
- package/dist/tools/delegates/unreal-assets.d.ts +2 -0
- package/dist/tools/delegates/unreal-assets.js +122 -0
- package/dist/tools/detection-tools.d.ts +2 -0
- package/dist/tools/detection-tools.js +164 -0
- package/dist/tools/detection-tools.js.map +1 -0
- package/dist/tools/index.d.ts +8 -0
- package/dist/tools/index.js +30 -0
- package/dist/tools/index.js.map +1 -0
- package/dist/tools/native/index.d.ts +2 -0
- package/dist/tools/native/index.js +1201 -0
- package/dist/tools/native-comprehension-tools.js +298 -0
- package/dist/tools/native-comprehension-tools.js.map +1 -0
- package/dist/tools/unpack-tools.d.ts +2 -0
- package/dist/tools/unpack-tools.js +382 -0
- package/dist/tools/workflow-tools.d.ts +2 -0
- package/dist/tools/workflow-tools.js +434 -0
- package/dist/utils/logger.d.ts +11 -0
- package/dist/utils/logger.js +49 -0
- package/dist/utils/logger.js.map +1 -0
- package/dist/utils/path-utils.d.ts +15 -0
- package/dist/utils/path-utils.js +24 -0
- package/dist/utils/path-utils.js.map +1 -0
- package/dist/utils/steam-finder.d.ts +8 -0
- package/dist/utils/steam-finder.js +32 -0
- package/dist/web/web-server.d.ts +1 -0
- package/dist/web/web-server.js +369 -0
- package/licenses/THIRD-PARTY-NOTICES.md +35 -0
- package/llms-install.md +34 -0
- package/package.json +69 -0
- package/server.json +20 -0
- package/setup.ps1 +34 -0
- package/ugm.config.json +9 -0
|
@@ -0,0 +1,517 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* model-db.ts — The Model SQLite writer (shared core).
|
|
3
|
+
*
|
|
4
|
+
* Owns the `<game>.autopsy.db` file: the single, portable, per-game persistent
|
|
5
|
+
* understanding the whole Autopsy Engine reads and writes. This module is the
|
|
6
|
+
* ONLY thing that knows the on-disk schema (MODEL_SCHEMA.md V1 subset).
|
|
7
|
+
*
|
|
8
|
+
* Design contract (PR-1):
|
|
9
|
+
* - better-sqlite3, synchronous. One file per game.
|
|
10
|
+
* - CREATE TABLE IF NOT EXISTS for game / binary / asset / data_store, every
|
|
11
|
+
* fact-bearing row carrying provenance + source_tool columns.
|
|
12
|
+
* - Idempotent writes: UNIQUE natural keys + INSERT ... ON CONFLICT DO UPDATE,
|
|
13
|
+
* so re-running unpack_game never duplicates rows (append-and-confirm).
|
|
14
|
+
* - WAL journal mode for crash safety.
|
|
15
|
+
* - Read-only with respect to GAME files. The only thing this writes is the
|
|
16
|
+
* .autopsy.db itself.
|
|
17
|
+
*/
|
|
18
|
+
import Database from 'better-sqlite3';
|
|
19
|
+
import { dirname } from 'path';
|
|
20
|
+
import { existsSync, mkdirSync } from 'fs';
|
|
21
|
+
/**
|
|
22
|
+
* The schema version this writer emits. Stored on the game row.
|
|
23
|
+
* v1 (PR-0): game / binary / asset / data_store.
|
|
24
|
+
* v2 (PR-3): + function / xref / symbol (ADDITIVE — v1 tables untouched; existing
|
|
25
|
+
* .autopsy.db files gain the empty new tables via CREATE TABLE IF NOT EXISTS).
|
|
26
|
+
*/
|
|
27
|
+
export const AUTOPSY_SCHEMA_VERSION = 2;
|
|
28
|
+
/**
|
|
29
|
+
* AutopsyModel — opens/creates a `<game>.autopsy.db` and writes the V1 tables.
|
|
30
|
+
*
|
|
31
|
+
* Usage:
|
|
32
|
+
* const model = new AutopsyModel('C:/.../MyGame.autopsy.db');
|
|
33
|
+
* const gameId = model.upsertGame({ ... });
|
|
34
|
+
* model.addBinary({ game_id: gameId, ... });
|
|
35
|
+
* ...
|
|
36
|
+
* model.close();
|
|
37
|
+
*/
|
|
38
|
+
export class AutopsyModel {
|
|
39
|
+
db;
|
|
40
|
+
dbPath;
|
|
41
|
+
constructor(dbPath) {
|
|
42
|
+
this.dbPath = dbPath;
|
|
43
|
+
// Ensure the containing directory exists (.autopsy/ dir or sibling of game).
|
|
44
|
+
const dir = dirname(dbPath);
|
|
45
|
+
if (dir && !existsSync(dir)) {
|
|
46
|
+
mkdirSync(dir, { recursive: true });
|
|
47
|
+
}
|
|
48
|
+
this.db = new Database(dbPath);
|
|
49
|
+
// WAL for crash safety + concurrent reads while we append.
|
|
50
|
+
this.db.pragma('journal_mode = WAL');
|
|
51
|
+
this.db.pragma('foreign_keys = ON');
|
|
52
|
+
// Reasonable durability without the full-fsync cost on every statement.
|
|
53
|
+
this.db.pragma('synchronous = NORMAL');
|
|
54
|
+
this.createSchema();
|
|
55
|
+
}
|
|
56
|
+
/** Create the V1 tables (idempotent). Called on every open. */
|
|
57
|
+
createSchema() {
|
|
58
|
+
this.db.exec(`
|
|
59
|
+
CREATE TABLE IF NOT EXISTS game (
|
|
60
|
+
id INTEGER PRIMARY KEY,
|
|
61
|
+
name TEXT NOT NULL,
|
|
62
|
+
install_path TEXT NOT NULL,
|
|
63
|
+
engine TEXT,
|
|
64
|
+
runtime TEXT,
|
|
65
|
+
arch TEXT,
|
|
66
|
+
package_type TEXT,
|
|
67
|
+
autopsy_version INTEGER NOT NULL,
|
|
68
|
+
provenance TEXT NOT NULL DEFAULT 'inferred',
|
|
69
|
+
source_tool TEXT NOT NULL DEFAULT 'unpack_game',
|
|
70
|
+
created_at TEXT NOT NULL DEFAULT (datetime('now')),
|
|
71
|
+
UNIQUE (install_path)
|
|
72
|
+
);
|
|
73
|
+
|
|
74
|
+
CREATE TABLE IF NOT EXISTS binary (
|
|
75
|
+
id INTEGER PRIMARY KEY,
|
|
76
|
+
game_id INTEGER NOT NULL REFERENCES game(id) ON DELETE CASCADE,
|
|
77
|
+
path TEXT NOT NULL,
|
|
78
|
+
kind TEXT NOT NULL,
|
|
79
|
+
managed INTEGER NOT NULL DEFAULT 0,
|
|
80
|
+
arch TEXT,
|
|
81
|
+
size INTEGER NOT NULL DEFAULT 0,
|
|
82
|
+
sha256 TEXT,
|
|
83
|
+
role TEXT,
|
|
84
|
+
notes TEXT,
|
|
85
|
+
provenance TEXT NOT NULL DEFAULT 'inferred',
|
|
86
|
+
source_tool TEXT NOT NULL DEFAULT 'unpack_game',
|
|
87
|
+
UNIQUE (game_id, path)
|
|
88
|
+
);
|
|
89
|
+
|
|
90
|
+
CREATE TABLE IF NOT EXISTS asset (
|
|
91
|
+
id INTEGER PRIMARY KEY,
|
|
92
|
+
game_id INTEGER NOT NULL REFERENCES game(id) ON DELETE CASCADE,
|
|
93
|
+
container_path TEXT NOT NULL,
|
|
94
|
+
internal_path TEXT NOT NULL DEFAULT '',
|
|
95
|
+
type TEXT NOT NULL DEFAULT 'other',
|
|
96
|
+
format TEXT,
|
|
97
|
+
decoded INTEGER NOT NULL DEFAULT 0,
|
|
98
|
+
decoded_path TEXT,
|
|
99
|
+
size INTEGER NOT NULL DEFAULT 0,
|
|
100
|
+
notes TEXT,
|
|
101
|
+
provenance TEXT NOT NULL DEFAULT 'inferred',
|
|
102
|
+
source_tool TEXT NOT NULL DEFAULT 'unpack_game',
|
|
103
|
+
UNIQUE (game_id, container_path, internal_path)
|
|
104
|
+
);
|
|
105
|
+
|
|
106
|
+
CREATE TABLE IF NOT EXISTS data_store (
|
|
107
|
+
id INTEGER PRIMARY KEY,
|
|
108
|
+
game_id INTEGER NOT NULL REFERENCES game(id) ON DELETE CASCADE,
|
|
109
|
+
path TEXT NOT NULL,
|
|
110
|
+
kind TEXT NOT NULL,
|
|
111
|
+
scope TEXT,
|
|
112
|
+
schema_known INTEGER NOT NULL DEFAULT 0,
|
|
113
|
+
notes TEXT,
|
|
114
|
+
provenance TEXT NOT NULL DEFAULT 'inferred',
|
|
115
|
+
source_tool TEXT NOT NULL DEFAULT 'unpack_game',
|
|
116
|
+
UNIQUE (game_id, path)
|
|
117
|
+
);
|
|
118
|
+
|
|
119
|
+
CREATE INDEX IF NOT EXISTS idx_binary_game ON binary(game_id);
|
|
120
|
+
CREATE INDEX IF NOT EXISTS idx_asset_game ON asset(game_id);
|
|
121
|
+
CREATE INDEX IF NOT EXISTS idx_asset_type ON asset(game_id, type);
|
|
122
|
+
CREATE INDEX IF NOT EXISTS idx_data_store_game ON data_store(game_id);
|
|
123
|
+
`);
|
|
124
|
+
// ── Schema v2 (PR-3, V3 Native Comprehension) — ADDITIVE ────────────────
|
|
125
|
+
// New tables only. The v1 block above is byte-for-byte unchanged, so existing
|
|
126
|
+
// .autopsy.db files simply gain these three empty tables on next open.
|
|
127
|
+
// NB: "function" is a SQL keyword — the identifier is double-quoted everywhere.
|
|
128
|
+
this.db.exec(`
|
|
129
|
+
CREATE TABLE IF NOT EXISTS "function" (
|
|
130
|
+
id INTEGER PRIMARY KEY,
|
|
131
|
+
binary_id INTEGER NOT NULL REFERENCES binary(id) ON DELETE CASCADE,
|
|
132
|
+
rva INTEGER NOT NULL,
|
|
133
|
+
size INTEGER NOT NULL DEFAULT 0,
|
|
134
|
+
insn_count INTEGER NOT NULL DEFAULT 0,
|
|
135
|
+
name TEXT,
|
|
136
|
+
label TEXT,
|
|
137
|
+
notes TEXT,
|
|
138
|
+
provenance TEXT NOT NULL DEFAULT 'inferred',
|
|
139
|
+
source_tool TEXT NOT NULL DEFAULT 'disassemble_function',
|
|
140
|
+
UNIQUE (binary_id, rva)
|
|
141
|
+
);
|
|
142
|
+
|
|
143
|
+
CREATE TABLE IF NOT EXISTS xref (
|
|
144
|
+
id INTEGER PRIMARY KEY,
|
|
145
|
+
binary_id INTEGER NOT NULL REFERENCES binary(id) ON DELETE CASCADE,
|
|
146
|
+
from_rva INTEGER NOT NULL,
|
|
147
|
+
to_rva INTEGER NOT NULL,
|
|
148
|
+
kind TEXT NOT NULL,
|
|
149
|
+
mnemonic TEXT,
|
|
150
|
+
notes TEXT,
|
|
151
|
+
provenance TEXT NOT NULL DEFAULT 'verified',
|
|
152
|
+
source_tool TEXT NOT NULL DEFAULT 'build_call_graph',
|
|
153
|
+
UNIQUE (binary_id, from_rva, to_rva, kind)
|
|
154
|
+
);
|
|
155
|
+
|
|
156
|
+
CREATE TABLE IF NOT EXISTS symbol (
|
|
157
|
+
id INTEGER PRIMARY KEY,
|
|
158
|
+
binary_id INTEGER NOT NULL REFERENCES binary(id) ON DELETE CASCADE,
|
|
159
|
+
rva INTEGER NOT NULL,
|
|
160
|
+
name TEXT NOT NULL,
|
|
161
|
+
kind TEXT NOT NULL,
|
|
162
|
+
notes TEXT,
|
|
163
|
+
provenance TEXT NOT NULL DEFAULT 'verified',
|
|
164
|
+
source_tool TEXT NOT NULL DEFAULT 'ingest_pdb',
|
|
165
|
+
UNIQUE (binary_id, rva, kind)
|
|
166
|
+
);
|
|
167
|
+
|
|
168
|
+
CREATE INDEX IF NOT EXISTS idx_function_binary ON "function"(binary_id);
|
|
169
|
+
CREATE INDEX IF NOT EXISTS idx_xref_binary ON xref(binary_id);
|
|
170
|
+
CREATE INDEX IF NOT EXISTS idx_xref_to ON xref(binary_id, to_rva);
|
|
171
|
+
CREATE INDEX IF NOT EXISTS idx_symbol_binary ON symbol(binary_id);
|
|
172
|
+
`);
|
|
173
|
+
}
|
|
174
|
+
/**
|
|
175
|
+
* Insert-or-update the single game header row, keyed by install_path.
|
|
176
|
+
* Returns the game_id (stable across re-runs — append-and-confirm, A6).
|
|
177
|
+
*/
|
|
178
|
+
upsertGame(input) {
|
|
179
|
+
const stmt = this.db.prepare(`
|
|
180
|
+
INSERT INTO game (
|
|
181
|
+
name, install_path, engine, runtime, arch, package_type,
|
|
182
|
+
autopsy_version, provenance, source_tool
|
|
183
|
+
) VALUES (
|
|
184
|
+
@name, @install_path, @engine, @runtime, @arch, @package_type,
|
|
185
|
+
@autopsy_version, @provenance, @source_tool
|
|
186
|
+
)
|
|
187
|
+
ON CONFLICT (install_path) DO UPDATE SET
|
|
188
|
+
name = excluded.name,
|
|
189
|
+
engine = excluded.engine,
|
|
190
|
+
runtime = excluded.runtime,
|
|
191
|
+
arch = excluded.arch,
|
|
192
|
+
package_type = excluded.package_type,
|
|
193
|
+
autopsy_version = excluded.autopsy_version,
|
|
194
|
+
provenance = excluded.provenance,
|
|
195
|
+
source_tool = excluded.source_tool
|
|
196
|
+
RETURNING id
|
|
197
|
+
`);
|
|
198
|
+
const row = stmt.get({
|
|
199
|
+
name: input.name,
|
|
200
|
+
install_path: input.install_path,
|
|
201
|
+
engine: input.engine,
|
|
202
|
+
runtime: input.runtime,
|
|
203
|
+
arch: input.arch,
|
|
204
|
+
package_type: input.package_type,
|
|
205
|
+
autopsy_version: input.autopsy_version,
|
|
206
|
+
provenance: input.provenance,
|
|
207
|
+
source_tool: input.source_tool,
|
|
208
|
+
});
|
|
209
|
+
if (!row) {
|
|
210
|
+
throw new Error('upsertGame: INSERT ... RETURNING id produced no row');
|
|
211
|
+
}
|
|
212
|
+
return row.id;
|
|
213
|
+
}
|
|
214
|
+
/**
|
|
215
|
+
* Insert-or-update a binary, keyed by (game_id, path). Idempotent (A6).
|
|
216
|
+
* Returns the binary id.
|
|
217
|
+
*/
|
|
218
|
+
addBinary(input) {
|
|
219
|
+
const stmt = this.db.prepare(`
|
|
220
|
+
INSERT INTO binary (
|
|
221
|
+
game_id, path, kind, managed, arch, size, sha256, role, notes,
|
|
222
|
+
provenance, source_tool
|
|
223
|
+
) VALUES (
|
|
224
|
+
@game_id, @path, @kind, @managed, @arch, @size, @sha256, @role, @notes,
|
|
225
|
+
@provenance, @source_tool
|
|
226
|
+
)
|
|
227
|
+
ON CONFLICT (game_id, path) DO UPDATE SET
|
|
228
|
+
kind = excluded.kind,
|
|
229
|
+
managed = excluded.managed,
|
|
230
|
+
arch = excluded.arch,
|
|
231
|
+
size = excluded.size,
|
|
232
|
+
sha256 = excluded.sha256,
|
|
233
|
+
role = excluded.role,
|
|
234
|
+
notes = excluded.notes,
|
|
235
|
+
provenance = excluded.provenance,
|
|
236
|
+
source_tool = excluded.source_tool
|
|
237
|
+
RETURNING id
|
|
238
|
+
`);
|
|
239
|
+
const row = stmt.get({
|
|
240
|
+
game_id: input.game_id,
|
|
241
|
+
path: input.path,
|
|
242
|
+
kind: input.kind,
|
|
243
|
+
managed: input.managed ? 1 : 0,
|
|
244
|
+
arch: input.arch,
|
|
245
|
+
size: input.size,
|
|
246
|
+
sha256: input.sha256,
|
|
247
|
+
role: input.role,
|
|
248
|
+
notes: input.notes,
|
|
249
|
+
provenance: input.provenance,
|
|
250
|
+
source_tool: input.source_tool,
|
|
251
|
+
});
|
|
252
|
+
if (!row) {
|
|
253
|
+
throw new Error('addBinary: INSERT ... RETURNING id produced no row');
|
|
254
|
+
}
|
|
255
|
+
return row.id;
|
|
256
|
+
}
|
|
257
|
+
/**
|
|
258
|
+
* Insert-or-update an asset, keyed by (game_id, container_path, internal_path).
|
|
259
|
+
* Idempotent (A6). Unknown files arrive here as type='other' with a reason in
|
|
260
|
+
* notes — they are catalogued, never dropped (A3). Returns the asset id.
|
|
261
|
+
*/
|
|
262
|
+
addAsset(input) {
|
|
263
|
+
const stmt = this.db.prepare(`
|
|
264
|
+
INSERT INTO asset (
|
|
265
|
+
game_id, container_path, internal_path, type, format, decoded,
|
|
266
|
+
decoded_path, size, notes, provenance, source_tool
|
|
267
|
+
) VALUES (
|
|
268
|
+
@game_id, @container_path, @internal_path, @type, @format, @decoded,
|
|
269
|
+
@decoded_path, @size, @notes, @provenance, @source_tool
|
|
270
|
+
)
|
|
271
|
+
ON CONFLICT (game_id, container_path, internal_path) DO UPDATE SET
|
|
272
|
+
type = excluded.type,
|
|
273
|
+
format = excluded.format,
|
|
274
|
+
decoded = excluded.decoded,
|
|
275
|
+
decoded_path = excluded.decoded_path,
|
|
276
|
+
size = excluded.size,
|
|
277
|
+
notes = excluded.notes,
|
|
278
|
+
provenance = excluded.provenance,
|
|
279
|
+
source_tool = excluded.source_tool
|
|
280
|
+
RETURNING id
|
|
281
|
+
`);
|
|
282
|
+
const row = stmt.get({
|
|
283
|
+
game_id: input.game_id,
|
|
284
|
+
container_path: input.container_path,
|
|
285
|
+
internal_path: input.internal_path ?? '',
|
|
286
|
+
type: input.type,
|
|
287
|
+
format: input.format,
|
|
288
|
+
decoded: input.decoded ? 1 : 0,
|
|
289
|
+
decoded_path: input.decoded_path,
|
|
290
|
+
size: input.size,
|
|
291
|
+
notes: input.notes,
|
|
292
|
+
provenance: input.provenance,
|
|
293
|
+
source_tool: input.source_tool,
|
|
294
|
+
});
|
|
295
|
+
if (!row) {
|
|
296
|
+
throw new Error('addAsset: INSERT ... RETURNING id produced no row');
|
|
297
|
+
}
|
|
298
|
+
return row.id;
|
|
299
|
+
}
|
|
300
|
+
/**
|
|
301
|
+
* Insert-or-update a data_store, keyed by (game_id, path). Idempotent (A6).
|
|
302
|
+
* Containers (.pak/.bundle/.pck) may land here as kind='binary-blob' rather
|
|
303
|
+
* than being walked as Unity (A7). Returns the data_store id.
|
|
304
|
+
*/
|
|
305
|
+
addDataStore(input) {
|
|
306
|
+
const stmt = this.db.prepare(`
|
|
307
|
+
INSERT INTO data_store (
|
|
308
|
+
game_id, path, kind, scope, schema_known, notes,
|
|
309
|
+
provenance, source_tool
|
|
310
|
+
) VALUES (
|
|
311
|
+
@game_id, @path, @kind, @scope, @schema_known, @notes,
|
|
312
|
+
@provenance, @source_tool
|
|
313
|
+
)
|
|
314
|
+
ON CONFLICT (game_id, path) DO UPDATE SET
|
|
315
|
+
kind = excluded.kind,
|
|
316
|
+
scope = excluded.scope,
|
|
317
|
+
schema_known = excluded.schema_known,
|
|
318
|
+
notes = excluded.notes,
|
|
319
|
+
provenance = excluded.provenance,
|
|
320
|
+
source_tool = excluded.source_tool
|
|
321
|
+
RETURNING id
|
|
322
|
+
`);
|
|
323
|
+
const row = stmt.get({
|
|
324
|
+
game_id: input.game_id,
|
|
325
|
+
path: input.path,
|
|
326
|
+
kind: input.kind,
|
|
327
|
+
scope: input.scope,
|
|
328
|
+
schema_known: input.schema_known ? 1 : 0,
|
|
329
|
+
notes: input.notes,
|
|
330
|
+
provenance: input.provenance,
|
|
331
|
+
source_tool: input.source_tool,
|
|
332
|
+
});
|
|
333
|
+
if (!row) {
|
|
334
|
+
throw new Error('addDataStore: INSERT ... RETURNING id produced no row');
|
|
335
|
+
}
|
|
336
|
+
return row.id;
|
|
337
|
+
}
|
|
338
|
+
/**
|
|
339
|
+
* Insert-or-update a function, keyed by (binary_id, rva). Idempotent (A6).
|
|
340
|
+
* PR-3.1 writes the disassembled region's extent; name/label fill in later
|
|
341
|
+
* slices. Returns the function id.
|
|
342
|
+
*/
|
|
343
|
+
addFunction(input) {
|
|
344
|
+
const stmt = this.db.prepare(`
|
|
345
|
+
INSERT INTO "function" (
|
|
346
|
+
binary_id, rva, size, insn_count, name, label, notes,
|
|
347
|
+
provenance, source_tool
|
|
348
|
+
) VALUES (
|
|
349
|
+
@binary_id, @rva, @size, @insn_count, @name, @label, @notes,
|
|
350
|
+
@provenance, @source_tool
|
|
351
|
+
)
|
|
352
|
+
ON CONFLICT (binary_id, rva) DO UPDATE SET
|
|
353
|
+
size = excluded.size,
|
|
354
|
+
insn_count = excluded.insn_count,
|
|
355
|
+
name = COALESCE(excluded.name, "function".name),
|
|
356
|
+
label = COALESCE(excluded.label, "function".label),
|
|
357
|
+
notes = excluded.notes,
|
|
358
|
+
provenance = excluded.provenance,
|
|
359
|
+
source_tool = excluded.source_tool
|
|
360
|
+
RETURNING id
|
|
361
|
+
`);
|
|
362
|
+
const row = stmt.get({
|
|
363
|
+
binary_id: input.binary_id,
|
|
364
|
+
rva: input.rva,
|
|
365
|
+
size: input.size,
|
|
366
|
+
insn_count: input.insn_count,
|
|
367
|
+
name: input.name,
|
|
368
|
+
label: input.label,
|
|
369
|
+
notes: input.notes,
|
|
370
|
+
provenance: input.provenance,
|
|
371
|
+
source_tool: input.source_tool,
|
|
372
|
+
});
|
|
373
|
+
if (!row) {
|
|
374
|
+
throw new Error('addFunction: INSERT ... RETURNING id produced no row');
|
|
375
|
+
}
|
|
376
|
+
return row.id;
|
|
377
|
+
}
|
|
378
|
+
/**
|
|
379
|
+
* Insert-or-update a cross-reference, keyed by (binary_id, from_rva, to_rva,
|
|
380
|
+
* kind). Idempotent (A6). Returns the xref id.
|
|
381
|
+
*/
|
|
382
|
+
addXref(input) {
|
|
383
|
+
const stmt = this.db.prepare(`
|
|
384
|
+
INSERT INTO xref (
|
|
385
|
+
binary_id, from_rva, to_rva, kind, mnemonic, notes,
|
|
386
|
+
provenance, source_tool
|
|
387
|
+
) VALUES (
|
|
388
|
+
@binary_id, @from_rva, @to_rva, @kind, @mnemonic, @notes,
|
|
389
|
+
@provenance, @source_tool
|
|
390
|
+
)
|
|
391
|
+
ON CONFLICT (binary_id, from_rva, to_rva, kind) DO UPDATE SET
|
|
392
|
+
mnemonic = excluded.mnemonic,
|
|
393
|
+
notes = excluded.notes,
|
|
394
|
+
provenance = excluded.provenance,
|
|
395
|
+
source_tool = excluded.source_tool
|
|
396
|
+
RETURNING id
|
|
397
|
+
`);
|
|
398
|
+
const row = stmt.get({
|
|
399
|
+
binary_id: input.binary_id,
|
|
400
|
+
from_rva: input.from_rva,
|
|
401
|
+
to_rva: input.to_rva,
|
|
402
|
+
kind: input.kind,
|
|
403
|
+
mnemonic: input.mnemonic,
|
|
404
|
+
notes: input.notes,
|
|
405
|
+
provenance: input.provenance,
|
|
406
|
+
source_tool: input.source_tool,
|
|
407
|
+
});
|
|
408
|
+
if (!row) {
|
|
409
|
+
throw new Error('addXref: INSERT ... RETURNING id produced no row');
|
|
410
|
+
}
|
|
411
|
+
return row.id;
|
|
412
|
+
}
|
|
413
|
+
/**
|
|
414
|
+
* Insert-or-update a symbol, keyed by (binary_id, rva, kind). Idempotent (A6).
|
|
415
|
+
* Returns the symbol id.
|
|
416
|
+
*/
|
|
417
|
+
addSymbol(input) {
|
|
418
|
+
const stmt = this.db.prepare(`
|
|
419
|
+
INSERT INTO symbol (
|
|
420
|
+
binary_id, rva, name, kind, notes, provenance, source_tool
|
|
421
|
+
) VALUES (
|
|
422
|
+
@binary_id, @rva, @name, @kind, @notes, @provenance, @source_tool
|
|
423
|
+
)
|
|
424
|
+
ON CONFLICT (binary_id, rva, kind) DO UPDATE SET
|
|
425
|
+
name = excluded.name,
|
|
426
|
+
notes = excluded.notes,
|
|
427
|
+
provenance = excluded.provenance,
|
|
428
|
+
source_tool = excluded.source_tool
|
|
429
|
+
RETURNING id
|
|
430
|
+
`);
|
|
431
|
+
const row = stmt.get({
|
|
432
|
+
binary_id: input.binary_id,
|
|
433
|
+
rva: input.rva,
|
|
434
|
+
name: input.name,
|
|
435
|
+
kind: input.kind,
|
|
436
|
+
notes: input.notes,
|
|
437
|
+
provenance: input.provenance,
|
|
438
|
+
source_tool: input.source_tool,
|
|
439
|
+
});
|
|
440
|
+
if (!row) {
|
|
441
|
+
throw new Error('addSymbol: INSERT ... RETURNING id produced no row');
|
|
442
|
+
}
|
|
443
|
+
return row.id;
|
|
444
|
+
}
|
|
445
|
+
/**
|
|
446
|
+
* Run many writes inside one transaction. Returns the callback's result.
|
|
447
|
+
* Far faster for a full-install walk, and atomic: a crash mid-walk leaves
|
|
448
|
+
* the DB at its prior consistent state rather than half-populated.
|
|
449
|
+
*/
|
|
450
|
+
transaction(fn) {
|
|
451
|
+
const wrapped = this.db.transaction(fn);
|
|
452
|
+
return wrapped();
|
|
453
|
+
}
|
|
454
|
+
/** Row counts per table — for the unpack summary / verifier / tests. */
|
|
455
|
+
counts() {
|
|
456
|
+
// `table` is a trusted literal from this method only (never user input).
|
|
457
|
+
// "function" is a SQL keyword, so callers pass the already-quoted identifier.
|
|
458
|
+
const one = (table) => {
|
|
459
|
+
const row = this.db
|
|
460
|
+
.prepare(`SELECT COUNT(*) AS n FROM ${table}`)
|
|
461
|
+
.get();
|
|
462
|
+
return row.n;
|
|
463
|
+
};
|
|
464
|
+
return {
|
|
465
|
+
game: one('game'),
|
|
466
|
+
binary: one('binary'),
|
|
467
|
+
asset: one('asset'),
|
|
468
|
+
data_store: one('data_store'),
|
|
469
|
+
function: one('"function"'),
|
|
470
|
+
xref: one('xref'),
|
|
471
|
+
symbol: one('symbol'),
|
|
472
|
+
};
|
|
473
|
+
}
|
|
474
|
+
/** Row counts scoped to a single game_id. Convenience for per-game summaries. */
|
|
475
|
+
countsForGame(gameId) {
|
|
476
|
+
const one = (table) => {
|
|
477
|
+
const row = this.db
|
|
478
|
+
.prepare(`SELECT COUNT(*) AS n FROM ${table} WHERE game_id = ?`)
|
|
479
|
+
.get(gameId);
|
|
480
|
+
return row.n;
|
|
481
|
+
};
|
|
482
|
+
// Native tables (v2) key on binary_id, so scope them through binary(game_id).
|
|
483
|
+
const viaBinary = (table) => {
|
|
484
|
+
const row = this.db
|
|
485
|
+
.prepare(`SELECT COUNT(*) AS n FROM ${table} t
|
|
486
|
+
JOIN binary b ON b.id = t.binary_id
|
|
487
|
+
WHERE b.game_id = ?`)
|
|
488
|
+
.get(gameId);
|
|
489
|
+
return row.n;
|
|
490
|
+
};
|
|
491
|
+
return {
|
|
492
|
+
// The game table is keyed on id, not game_id.
|
|
493
|
+
game: this.db.prepare('SELECT COUNT(*) AS n FROM game WHERE id = ?').get(gameId).n,
|
|
494
|
+
binary: one('binary'),
|
|
495
|
+
asset: one('asset'),
|
|
496
|
+
data_store: one('data_store'),
|
|
497
|
+
function: viaBinary('"function"'),
|
|
498
|
+
xref: viaBinary('xref'),
|
|
499
|
+
symbol: viaBinary('symbol'),
|
|
500
|
+
};
|
|
501
|
+
}
|
|
502
|
+
/** Escape hatch for verifiers/tests that need a raw read. Read-only by convention. */
|
|
503
|
+
raw() {
|
|
504
|
+
return this.db;
|
|
505
|
+
}
|
|
506
|
+
/** Flush WAL back into the main DB and close the handle. */
|
|
507
|
+
close() {
|
|
508
|
+
try {
|
|
509
|
+
this.db.pragma('wal_checkpoint(TRUNCATE)');
|
|
510
|
+
}
|
|
511
|
+
catch {
|
|
512
|
+
// Best-effort checkpoint; closing is what matters.
|
|
513
|
+
}
|
|
514
|
+
this.db.close();
|
|
515
|
+
}
|
|
516
|
+
}
|
|
517
|
+
//# sourceMappingURL=model-db.js.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"model-db.js","sourceRoot":"","sources":["../../src/core/model-db.ts"],"names":[],"mappings":"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"}
|
|
@@ -0,0 +1,6 @@
|
|
|
1
|
+
import { BackendName } from '../backends/child-pool.js';
|
|
2
|
+
export type ToolBackend = 'native' | 'workflow' | BackendName;
|
|
3
|
+
export declare function getToolBackend(toolName: string): ToolBackend | undefined;
|
|
4
|
+
export declare function getAllToolNames(): string[];
|
|
5
|
+
export declare function getToolsByBackend(backend: ToolBackend): string[];
|
|
6
|
+
export declare function isValidTool(toolName: string): boolean;
|
|
@@ -0,0 +1,143 @@
|
|
|
1
|
+
// Static route map: tool name -> backend
|
|
2
|
+
const ROUTE_MAP = new Map([
|
|
3
|
+
// === Detection & Session (workflow) ===
|
|
4
|
+
['detect_engine', 'workflow'],
|
|
5
|
+
['load_game', 'workflow'],
|
|
6
|
+
['game_status', 'workflow'],
|
|
7
|
+
['list_available_tools', 'workflow'],
|
|
8
|
+
['find_steam_games', 'workflow'],
|
|
9
|
+
// === Workflow Tools ===
|
|
10
|
+
['mod_this_game', 'workflow'],
|
|
11
|
+
['find_gameplay_values', 'workflow'],
|
|
12
|
+
['build_and_deploy', 'workflow'],
|
|
13
|
+
['debug_mod', 'workflow'],
|
|
14
|
+
['scaffold_mod', 'workflow'],
|
|
15
|
+
// === Native Analysis Tools (ported from binary-analyzer-ultra) ===
|
|
16
|
+
['analyze_pe_full', 'native'],
|
|
17
|
+
['analyze_dll_exports', 'native'],
|
|
18
|
+
['analyze_dll_imports', 'native'],
|
|
19
|
+
['analyze_file_format', 'native'],
|
|
20
|
+
['analyze_memory_layout', 'native'],
|
|
21
|
+
['hex_read', 'native'],
|
|
22
|
+
['hex_write', 'native'],
|
|
23
|
+
['hex_search', 'native'],
|
|
24
|
+
['hex_replace', 'native'],
|
|
25
|
+
['pattern_scan', 'native'],
|
|
26
|
+
['pattern_scan_all', 'native'],
|
|
27
|
+
['extract_strings_advanced', 'native'],
|
|
28
|
+
['extract_resources_full', 'native'],
|
|
29
|
+
['edit_string_table', 'native'],
|
|
30
|
+
['inject_resource', 'native'],
|
|
31
|
+
['compare_binaries_detailed', 'native'],
|
|
32
|
+
['calculate_checksums', 'native'],
|
|
33
|
+
['fix_pe_checksum', 'native'],
|
|
34
|
+
['rva_to_offset', 'native'],
|
|
35
|
+
['offset_to_rva', 'native'],
|
|
36
|
+
['disassemble_function', 'native'],
|
|
37
|
+
['create_patch', 'native'],
|
|
38
|
+
['apply_patch', 'native'],
|
|
39
|
+
['compress_file', 'native'],
|
|
40
|
+
['decompress_file', 'native'],
|
|
41
|
+
['encrypt_decrypt_file', 'native'],
|
|
42
|
+
['analyze_wad', 'native'],
|
|
43
|
+
// IL2CPP native tools
|
|
44
|
+
['unity_il2cpp_dump_metadata', 'native'],
|
|
45
|
+
['unity_il2cpp_find_class', 'native'],
|
|
46
|
+
['actk_scan_obscured_values', 'native'],
|
|
47
|
+
['actk_decrypt_value', 'native'],
|
|
48
|
+
['actk_struct_info', 'native'],
|
|
49
|
+
// PlayerPrefs native tools
|
|
50
|
+
['unity_playerprefs_read', 'native'],
|
|
51
|
+
['unity_playerprefs_write', 'native'],
|
|
52
|
+
// Godot native tools
|
|
53
|
+
['analyze_godot_pck', 'native'],
|
|
54
|
+
// Game save tools
|
|
55
|
+
['analyze_game_save', 'native'],
|
|
56
|
+
// Smart binary analyzer (ported)
|
|
57
|
+
['search_binary_pattern', 'native'],
|
|
58
|
+
['extract_dll_classes', 'native'],
|
|
59
|
+
['extract_strings', 'native'],
|
|
60
|
+
['analyze_dll_structure', 'native'],
|
|
61
|
+
// === Unity Mono Delegate (-> UnityDecompilerMcp.exe) ===
|
|
62
|
+
['load_assembly', 'unity-decompiler'],
|
|
63
|
+
['list_types', 'unity-decompiler'],
|
|
64
|
+
['inspect_type', 'unity-decompiler'],
|
|
65
|
+
['decompile_type', 'unity-decompiler'],
|
|
66
|
+
['decompile_method', 'unity-decompiler'],
|
|
67
|
+
['get_method_il', 'unity-decompiler'],
|
|
68
|
+
['search_code', 'unity-decompiler'],
|
|
69
|
+
['find_references', 'unity-decompiler'],
|
|
70
|
+
['get_inheritance_tree', 'unity-decompiler'],
|
|
71
|
+
['list_monobehaviours', 'unity-decompiler'],
|
|
72
|
+
['list_scriptableobjects', 'unity-decompiler'],
|
|
73
|
+
['get_serialized_fields', 'unity-decompiler'],
|
|
74
|
+
['generate_harmony_patch', 'unity-decompiler'],
|
|
75
|
+
['generate_plugin', 'unity-decompiler'],
|
|
76
|
+
['compile_plugin', 'unity-decompiler'],
|
|
77
|
+
['validate_assembly', 'unity-decompiler'],
|
|
78
|
+
['validate_patch_target', 'unity-decompiler'],
|
|
79
|
+
['verify_patches', 'unity-decompiler'],
|
|
80
|
+
['compare_signatures', 'unity-decompiler'],
|
|
81
|
+
['diff_assemblies', 'unity-decompiler'],
|
|
82
|
+
['find_renamed_types', 'unity-decompiler'],
|
|
83
|
+
['detect_networking', 'unity-decompiler'],
|
|
84
|
+
['analyze_bepinex_log', 'unity-decompiler'],
|
|
85
|
+
['analyze_save_format', 'unity-decompiler'],
|
|
86
|
+
['read_playerprefs', 'unity-decompiler'],
|
|
87
|
+
['read_unity_assets_info', 'unity-decompiler'],
|
|
88
|
+
['list_patchable_methods', 'unity-decompiler'],
|
|
89
|
+
// === Unreal Delegate (-> UnrealAssetMcp.exe) ===
|
|
90
|
+
['open_game', 'unreal-assets'],
|
|
91
|
+
['unreal_game_status', 'unreal-assets'],
|
|
92
|
+
['list_assets', 'unreal-assets'],
|
|
93
|
+
['search_assets', 'unreal-assets'],
|
|
94
|
+
['read_asset', 'unreal-assets'],
|
|
95
|
+
['read_asset_export', 'unreal-assets'],
|
|
96
|
+
['list_exports', 'unreal-assets'],
|
|
97
|
+
['read_blueprint', 'unreal-assets'],
|
|
98
|
+
['find_blueprints_of_type', 'unreal-assets'],
|
|
99
|
+
['read_datatable', 'unreal-assets'],
|
|
100
|
+
['get_class_hierarchy', 'unreal-assets'],
|
|
101
|
+
// === Java Delegate (-> jar-editor server.py) ===
|
|
102
|
+
['jar_open', 'jar-editor'],
|
|
103
|
+
['jar_close', 'jar-editor'],
|
|
104
|
+
['jar_list', 'jar-editor'],
|
|
105
|
+
['jar_list_sessions', 'jar-editor'],
|
|
106
|
+
['jar_read_class', 'jar-editor'],
|
|
107
|
+
['jar_read_file', 'jar-editor'],
|
|
108
|
+
['jar_search', 'jar-editor'],
|
|
109
|
+
['jar_search_bytecode', 'jar-editor'],
|
|
110
|
+
['jar_search_opcodes', 'jar-editor'],
|
|
111
|
+
['jar_inspect_constant_pool', 'jar-editor'],
|
|
112
|
+
['jar_edit_class_constants', 'jar-editor'],
|
|
113
|
+
['jar_edit_constant_pool', 'jar-editor'],
|
|
114
|
+
['jar_edit_file', 'jar-editor'],
|
|
115
|
+
['jar_hex_edit', 'jar-editor'],
|
|
116
|
+
['jar_hex_view', 'jar-editor'],
|
|
117
|
+
['jar_compile_java', 'jar-editor'],
|
|
118
|
+
['jar_repack', 'jar-editor'],
|
|
119
|
+
['jar_diff', 'jar-editor'],
|
|
120
|
+
['jar_add_file', 'jar-editor'],
|
|
121
|
+
['jar_add_file_content', 'jar-editor'],
|
|
122
|
+
['jar_restore_file', 'jar-editor'],
|
|
123
|
+
['jar_scaffold_mod', 'jar-editor'],
|
|
124
|
+
['jar_preset_apply', 'jar-editor'],
|
|
125
|
+
['jar_preset_list', 'jar-editor'],
|
|
126
|
+
['jar_preset_save', 'jar-editor'],
|
|
127
|
+
['jar_detect_mod_info', 'jar-editor'],
|
|
128
|
+
]);
|
|
129
|
+
export function getToolBackend(toolName) {
|
|
130
|
+
return ROUTE_MAP.get(toolName);
|
|
131
|
+
}
|
|
132
|
+
export function getAllToolNames() {
|
|
133
|
+
return Array.from(ROUTE_MAP.keys());
|
|
134
|
+
}
|
|
135
|
+
export function getToolsByBackend(backend) {
|
|
136
|
+
return Array.from(ROUTE_MAP.entries())
|
|
137
|
+
.filter(([_, b]) => b === backend)
|
|
138
|
+
.map(([name]) => name);
|
|
139
|
+
}
|
|
140
|
+
export function isValidTool(toolName) {
|
|
141
|
+
return ROUTE_MAP.has(toolName);
|
|
142
|
+
}
|
|
143
|
+
//# sourceMappingURL=router.js.map
|