decomp: add toggle for automatic dgo overrides during auto decomp (#349)

* decomp: add toggle for automatic dgo overrides during auto decomp

* prettier

* lint
This commit is contained in:
Hat Kid 2024-05-06 04:13:40 +02:00 committed by GitHub
parent 5d6b63efbe
commit 88d81f1a72
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 92 additions and 24 deletions

View file

@ -83,6 +83,10 @@
"command": "opengoal.decomp.toggleAutoDecompilation",
"title": "OpenGOAL - Toggle Auto-Decompilation"
},
{
"command": "opengoal.decomp.toggleAutoDecompDGO",
"title": "OpenGOAL - Toggle DGO overrides for Auto-Decompilation"
},
{
"command": "opengoal.decomp.updateSourceFile",
"title": "OpenGOAL - Copy Decompilation to Source File"
@ -231,7 +235,12 @@
"opengoal.autoDecompilation": {
"type": "boolean",
"default": true,
"description": "Automatically active IR2 files"
"description": "Automatically decompile active IR2 files"
},
"opengoal.autoDecompDGO": {
"type": "boolean",
"default": true,
"description": "Try to automatically determine the DGO files needed for the auto decomp input"
},
"opengoal.eeManPagePath": {
"type": [

View file

@ -34,6 +34,7 @@ export function getConfig() {
"ntsc_v1",
),
autoDecompilation: configOptions.get<boolean>("autoDecompilation"),
autoDecompDGO: configOptions.get<boolean>("autoDecompDGO"),
colorsGoalGlobals: configOptions.get<string>("colors.goal.entity.global"),
colorsGoalStorageControl: configOptions.get<string>(
"colors.goal.storage.control",
@ -69,6 +70,15 @@ export async function updateAutoDecompilation(val: boolean) {
);
}
export async function updateAutoDecompDGO(val: boolean) {
const userConfig = vscode.workspace.getConfiguration();
await userConfig.update(
"opengoal.autoDecompDGO",
val,
vscode.ConfigurationTarget.Global,
);
}
export async function updateEeManPagePath(path: string) {
const userConfig = vscode.workspace.getConfiguration();
await userConfig.update(

View file

@ -6,6 +6,7 @@ import { open_in_pdf } from "./man-page";
import * as util from "util";
import {
getConfig,
updateAutoDecompDGO,
updateAutoDecompilation,
updateDecompilerPath,
updateFormatterPath,
@ -201,6 +202,54 @@ async function checkFormatterPath(): Promise<string | undefined> {
return formatterPath;
}
async function parseAllObjs(gameName: string) {
const objsPath = path.join(
getProjectRoot().fsPath,
"goal_src",
gameName,
"build",
"all_objs.json",
);
if (!existsSync(objsPath)) {
return undefined;
}
const objsData = await fs.readFile(objsPath, {
encoding: "utf-8",
});
return JSON.parse(objsData);
}
// get all the DGOs needed for the input files to pass to the config override
async function getDgosForInput(gameName: string, files: string[]) {
const dgos = [];
const objs = await parseAllObjs(gameName);
for (const file of files) {
const obj = objs.find((obj: any) => obj[0] === file);
const obj_dgos = obj[3];
for (const dgo in obj_dgos) {
const name = obj_dgos[dgo];
let extension;
switch (name) {
case "ART":
case "KERNEL":
case "ENGINE":
case "GAME":
case "COMMON":
extension = "CGO";
break;
default:
extension = "DGO";
}
const dgo_name = `"${extension}/${name}.${extension}"`;
// ignore duplicates
if (dgos.indexOf(dgo_name) === -1) {
dgos.push(dgo_name);
}
}
}
return dgos;
}
async function decompFiles(
gameName: GameName,
fileNames: string[],
@ -209,7 +258,7 @@ async function decompFiles(
const decompConfig = getDecompilerConfig(gameName);
if (decompConfig === undefined) {
await vscode.window.showErrorMessage(
`OpenGOAL - Can't decompile no ${gameName.toString} config selected`,
`OpenGOAL - Can't decompile, no ${gameName.toString} config selected`,
);
return;
}
@ -222,6 +271,9 @@ async function decompFiles(
}
const allowed_objects = fileNames.map((name) => `"${name}"`).join(",");
const dgo_override = getConfig().autoDecompDGO
? await getDgosForInput(gameName, fileNames)
: [];
updateStatus(DecompStatus.Decompiling, {
objectNames: fileNames,
decompConfig: path.parse(decompConfig).name,
@ -236,15 +288,15 @@ async function decompFiles(
getDecompilerConfigVersion(gameName),
"--config-override",
];
let override = `{"decompile_code": true, "print_cfgs": true, "levels_extract": false, `;
if (omitVariableCasts) {
args.push(
`{"decompile_code": true, "print_cfgs": true, "levels_extract": false, "ignore_var_name_casts": true,"allowed_objects": [${allowed_objects}]}`,
);
} else {
args.push(
`{"decompile_code": true, "print_cfgs": true, "levels_extract": false, "allowed_objects": [${allowed_objects}]}`,
);
override += `"ignore_var_name_casts": true, `;
}
if (dgo_override.length > 0) {
override += `"dgo_names": [${dgo_override}], `;
}
override += `"allowed_objects": [${allowed_objects}]}`;
args.push(override);
const { stdout, stderr } = await execFileAsync(decompilerPath, args, {
encoding: "utf8",
cwd: getProjectRoot()?.fsPath,
@ -305,21 +357,7 @@ async function decompFiles(
}
async function getValidObjectNames(gameName: string) {
// Look for the `all_objs.json` file
const objsPath = path.join(
getProjectRoot().fsPath,
"goal_src",
gameName,
"build",
"all_objs.json",
);
if (!existsSync(objsPath)) {
return undefined;
}
const objsData = await fs.readFile(objsPath, {
encoding: "utf-8",
});
const objs = JSON.parse(objsData);
const objs = await parseAllObjs(gameName.toString());
const names = [];
for (const obj of objs) {
const is_tpage = obj[0].includes("tpage");
@ -502,6 +540,11 @@ async function toggleAutoDecompilation() {
updateStatusBar(false, false);
}
async function toggleAutoDecompDGO() {
const isEnabled = getConfig().autoDecompDGO;
await updateAutoDecompDGO(!isEnabled);
}
async function updateSourceFile() {
const editor = vscode.window.activeTextEditor;
if (!editor || !editor.document === undefined) {
@ -751,6 +794,12 @@ export async function activateDecompTools() {
toggleAutoDecompilation,
),
);
getExtensionContext().subscriptions.push(
vscode.commands.registerCommand(
"opengoal.decomp.toggleAutoDecompDGO",
toggleAutoDecompDGO,
),
);
getExtensionContext().subscriptions.push(
vscode.commands.registerCommand(
"opengoal.decomp.updateSourceFile",