diff --git a/package.json b/package.json index ca0b474..08eb563 100644 --- a/package.json +++ b/package.json @@ -131,6 +131,10 @@ "command": "opengoal.decomp.misc.genMethodStubs", "title": "OpenGOAL - Misc - Generate Method Stubs" }, + { + "command": "opengoal.decomp.misc.applyDecompilerSuggestions", + "title": "OpenGOAL - Misc - Apply Decompiler Suggestions to Selection" + }, { "command": "opengoal.decomp.typeSearcher.open", "title": "OpenGOAL - Misc - Type Searcher" @@ -234,12 +238,17 @@ "opengoal.decompilerJak1ConfigVersion": { "type": "string", "default": "ntsc_v1", - "description": "Config version to use for decompiling jak 1 related files" + "description": "Config version to use for decompiling Jak 1 related files" }, "opengoal.decompilerJak2ConfigVersion": { "type": "string", "default": "ntsc_v1", - "description": "Config version to use for decompiling jak 2 related files" + "description": "Config version to use for decompiling Jak 2 related files" + }, + "opengoal.decompilerJak3ConfigVersion": { + "type": "string", + "default": "ntsc_v1", + "description": "Config version to use for decompiling Jak 3 related files" } } }, diff --git a/src/config/config.ts b/src/config/config.ts index 84ffe05..a3ea048 100644 --- a/src/config/config.ts +++ b/src/config/config.ts @@ -25,6 +25,10 @@ export function getConfig() { "decompilerJak2ConfigVersion", "ntsc_v1", ), + jak3DecompConfigVersion: configOptions.get( + "decompilerJak3ConfigVersion", + "ntsc_v1", + ), colorsGoalGlobals: configOptions.get("colors.goal.entity.global"), colorsGoalStorageControl: configOptions.get( "colors.goal.storage.control", diff --git a/src/decomp/decomp-tools.ts b/src/decomp/decomp-tools.ts index e49b231..4694514 100644 --- a/src/decomp/decomp-tools.ts +++ b/src/decomp/decomp-tools.ts @@ -92,6 +92,11 @@ function getDecompilerConfig(gameName: GameName): string | undefined { getProjectRoot(), `decompiler/config/jak2/jak2_config.jsonc`, ).fsPath; + } else if (gameName == GameName.Jak3) { + decompConfigPath = vscode.Uri.joinPath( + getProjectRoot(), + `decompiler/config/jak3/jak3_config.jsonc`, + ).fsPath; } if (decompConfigPath === undefined || !existsSync(decompConfigPath)) { return undefined; @@ -106,6 +111,8 @@ function getDecompilerConfigVersion(gameName: GameName): string { version = getConfig().jak1DecompConfigVersion; } else if (gameName == GameName.Jak2) { version = getConfig().jak2DecompConfigVersion; + } else if (gameName == GameName.Jak3) { + version = getConfig().jak3DecompConfigVersion; } if (version === undefined) { return "ntsc_v1"; @@ -221,7 +228,7 @@ async function decompSpecificFile() { // Prompt the user for the game name let gameName; const gameNameSelection = await vscode.window.showQuickPick( - ["jak1", "jak2"], + ["jak1", "jak2", "jak3"], { title: "Game?", }, @@ -234,8 +241,10 @@ async function decompSpecificFile() { } else { if (gameNameSelection == "jak1") { gameName = GameName.Jak1; - } else { + } else if (gameNameSelection == "jak2") { gameName = GameName.Jak2; + } else if (gameNameSelection == "jak3") { + gameName = GameName.Jak3; } } const validNames = await getValidObjectNames(gameNameSelection); @@ -318,6 +327,7 @@ async function decompAllActiveFiles() { ), ); jak1ObjectNames = [...new Set(jak1ObjectNames)]; + let jak2ObjectNames = truncateFileNameEndings( getFileNamesFromUris(getUrisFromTabs(/.*jak2\/.*_ir2\.asm/)), "_ir2.asm", @@ -330,11 +340,23 @@ async function decompAllActiveFiles() { ); jak2ObjectNames = [...new Set(jak2ObjectNames)]; + let jak3ObjectNames = truncateFileNameEndings( + getFileNamesFromUris(getUrisFromTabs(/.*jak3\/.*_ir2\.asm/)), + "_ir2.asm", + ); + jak3ObjectNames = jak3ObjectNames.concat( + truncateFileNameEndings( + getFileNamesFromUris(getUrisFromTabs(/.*jak3\/.*_disasm\.gc/)), + "_disasm.gc", + ), + ); + jak3ObjectNames = [...new Set(jak3ObjectNames)]; + if (jak1ObjectNames.length > 0) { const jak1Config = getDecompilerConfig(GameName.Jak1); if (jak1Config === undefined) { await vscode.window.showErrorMessage( - "OpenGOAL - Can't decompile no Jak 1 config selected", + "OpenGOAL - Can't decompile, no Jak 1 config selected", ); return; } @@ -345,12 +367,22 @@ async function decompAllActiveFiles() { const jak2Config = getDecompilerConfig(GameName.Jak2); if (jak2Config === undefined) { await vscode.window.showErrorMessage( - "OpenGOAL - Can't decompile no Jak 2 config selected", + "OpenGOAL - Can't decompile, no Jak 2 config selected", ); return; } await decompFiles(jak2Config, GameName.Jak2, jak2ObjectNames); } + if (jak3ObjectNames.length > 0) { + const jak3Config = getDecompilerConfig(GameName.Jak3); + if (jak3Config === undefined) { + await vscode.window.showErrorMessage( + "OpenGOAL - Can't decompile, no Jak 3 config selected", + ); + return; + } + await decompFiles(jak3Config, GameName.Jak3, jak3ObjectNames); + } } function openManPage() { @@ -419,6 +451,8 @@ async function updateSourceFile() { let gameName = "jak1"; if (editor.document.uri.fsPath.includes("jak2")) { gameName = "jak2"; + } else if (editor.document.uri.fsPath.includes("jak3")) { + gameName = "jak3"; } const { stdout, stderr } = await execAsync( @@ -463,6 +497,8 @@ async function updateReferenceTest() { let gameName = "jak1"; if (editor.document.uri.fsPath.includes("jak2")) { gameName = "jak2"; + } else if (editor.document.uri.fsPath.includes("jak3")) { + gameName = "jak3"; } const folderToSearch = vscode.Uri.joinPath( getProjectRoot(), diff --git a/src/decomp/misc-tools.ts b/src/decomp/misc-tools.ts index e2e2c78..0679eae 100644 --- a/src/decomp/misc-tools.ts +++ b/src/decomp/misc-tools.ts @@ -103,6 +103,8 @@ async function preserveBlock() { let gameName = "jak1"; if (game === GameName.Jak2) { gameName = "jak2"; + } else if (game === GameName.Jak3) { + gameName = "jak3"; } const gsrcPath = await findFileInGoalSrc(projectRoot, gameName, fileName); @@ -437,6 +439,22 @@ async function genMethodStubs() { return; } +async function applyDecompilerSuggestions() { + const editor = vscode.window.activeTextEditor; + if (editor === undefined || editor.selection.isEmpty) { + return; + } + + editor.edit((selectedText) => { + const content = editor.document.getText(editor.selection); + const result = content.replace( + /\(define-extern (\S+) (\S+)\) ;; (.+)/g, + "(define-extern $1 $3)", + ); + selectedText.replace(editor.selection, result); + }); +} + export async function activateMiscDecompTools() { getExtensionContext().subscriptions.push( vscode.commands.registerCommand( @@ -480,4 +498,10 @@ export async function activateMiscDecompTools() { genMethodStubs, ), ); + getExtensionContext().subscriptions.push( + vscode.commands.registerCommand( + "opengoal.decomp.misc.applyDecompilerSuggestions", + applyDecompilerSuggestions, + ), + ); } diff --git a/src/decomp/utils.ts b/src/decomp/utils.ts index 67685ee..6b648c6 100644 --- a/src/decomp/utils.ts +++ b/src/decomp/utils.ts @@ -21,13 +21,18 @@ export function getCastFileData( if (gameName == GameName.Jak1) { castFilePath = vscode.Uri.joinPath( projectRoot, - `decompiler/config/jak1/${config.jak2DecompConfigVersion}/${fileName}`, + `decompiler/config/jak1/${config.jak1DecompConfigVersion}/${fileName}`, ).fsPath; } else if (gameName == GameName.Jak2) { castFilePath = vscode.Uri.joinPath( projectRoot, `decompiler/config/jak2/${config.jak2DecompConfigVersion}/${fileName}`, ).fsPath; + } else if (gameName == GameName.Jak3) { + castFilePath = vscode.Uri.joinPath( + projectRoot, + `decompiler/config/jak3/${config.jak3DecompConfigVersion}/${fileName}`, + ).fsPath; } if (!existsSync(castFilePath)) { return undefined; @@ -59,7 +64,13 @@ export function getDecompilerConfigDirectory( decompConfigPath = vscode.Uri.joinPath( projectRoot, `decompiler/config/jak2/`, - getConfig().jak1DecompConfigVersion, + getConfig().jak2DecompConfigVersion, + ).fsPath; + } else if (gameName == GameName.Jak3) { + decompConfigPath = vscode.Uri.joinPath( + projectRoot, + `decompiler/config/jak3/`, + getConfig().jak3DecompConfigVersion, ).fsPath; } if (decompConfigPath === undefined || !existsSync(decompConfigPath)) { diff --git a/src/utils/file-utils.ts b/src/utils/file-utils.ts index 6e57226..d9153aa 100644 --- a/src/utils/file-utils.ts +++ b/src/utils/file-utils.ts @@ -6,6 +6,7 @@ import { getRecentFiles } from "../context"; export enum GameName { Jak1 = "jak1", Jak2 = "jak2", + Jak3 = "jak3", } const fileSwitchingAssoc = { @@ -51,6 +52,8 @@ export function determineGameFromPath(path: vscode.Uri): GameName | undefined { return GameName.Jak1; } else if (path.fsPath.includes("jak2")) { return GameName.Jak2; + } else if (path.fsPath.includes("jak3")) { + return GameName.Jak3; } return undefined; } @@ -58,11 +61,13 @@ export function determineGameFromPath(path: vscode.Uri): GameName | undefined { export function determineGameFromAllTypes( path: vscode.Uri, ): GameName | undefined { - if (path.fsPath.includes("jak2")) { + if (path.fsPath.includes("jak1")) { + return GameName.Jak1; + } else if (path.fsPath.includes("jak2")) { return GameName.Jak2; + } else if (path.fsPath.includes("jak3")) { + return GameName.Jak3; } - // jak 1 isn't in it's own folder sadly - return GameName.Jak1; } export async function getDirectoriesInDir(dir: string) {