Merge pull request #327 from open-goal/h/j3-decomp

decomp: jak 3 support
This commit is contained in:
Hat Kid 2024-01-18 20:32:46 +01:00 committed by GitHub
commit 92a1a1163a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
6 changed files with 100 additions and 11 deletions

View file

@ -131,6 +131,10 @@
"command": "opengoal.decomp.misc.genMethodStubs", "command": "opengoal.decomp.misc.genMethodStubs",
"title": "OpenGOAL - Misc - Generate Method Stubs" "title": "OpenGOAL - Misc - Generate Method Stubs"
}, },
{
"command": "opengoal.decomp.misc.applyDecompilerSuggestions",
"title": "OpenGOAL - Misc - Apply Decompiler Suggestions to Selection"
},
{ {
"command": "opengoal.decomp.typeSearcher.open", "command": "opengoal.decomp.typeSearcher.open",
"title": "OpenGOAL - Misc - Type Searcher" "title": "OpenGOAL - Misc - Type Searcher"
@ -234,12 +238,17 @@
"opengoal.decompilerJak1ConfigVersion": { "opengoal.decompilerJak1ConfigVersion": {
"type": "string", "type": "string",
"default": "ntsc_v1", "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": { "opengoal.decompilerJak2ConfigVersion": {
"type": "string", "type": "string",
"default": "ntsc_v1", "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"
} }
} }
}, },

View file

@ -25,6 +25,10 @@ export function getConfig() {
"decompilerJak2ConfigVersion", "decompilerJak2ConfigVersion",
"ntsc_v1", "ntsc_v1",
), ),
jak3DecompConfigVersion: configOptions.get<string>(
"decompilerJak3ConfigVersion",
"ntsc_v1",
),
colorsGoalGlobals: configOptions.get<string>("colors.goal.entity.global"), colorsGoalGlobals: configOptions.get<string>("colors.goal.entity.global"),
colorsGoalStorageControl: configOptions.get<string>( colorsGoalStorageControl: configOptions.get<string>(
"colors.goal.storage.control", "colors.goal.storage.control",

View file

@ -92,6 +92,11 @@ function getDecompilerConfig(gameName: GameName): string | undefined {
getProjectRoot(), getProjectRoot(),
`decompiler/config/jak2/jak2_config.jsonc`, `decompiler/config/jak2/jak2_config.jsonc`,
).fsPath; ).fsPath;
} else if (gameName == GameName.Jak3) {
decompConfigPath = vscode.Uri.joinPath(
getProjectRoot(),
`decompiler/config/jak3/jak3_config.jsonc`,
).fsPath;
} }
if (decompConfigPath === undefined || !existsSync(decompConfigPath)) { if (decompConfigPath === undefined || !existsSync(decompConfigPath)) {
return undefined; return undefined;
@ -106,6 +111,8 @@ function getDecompilerConfigVersion(gameName: GameName): string {
version = getConfig().jak1DecompConfigVersion; version = getConfig().jak1DecompConfigVersion;
} else if (gameName == GameName.Jak2) { } else if (gameName == GameName.Jak2) {
version = getConfig().jak2DecompConfigVersion; version = getConfig().jak2DecompConfigVersion;
} else if (gameName == GameName.Jak3) {
version = getConfig().jak3DecompConfigVersion;
} }
if (version === undefined) { if (version === undefined) {
return "ntsc_v1"; return "ntsc_v1";
@ -221,7 +228,7 @@ async function decompSpecificFile() {
// Prompt the user for the game name // Prompt the user for the game name
let gameName; let gameName;
const gameNameSelection = await vscode.window.showQuickPick( const gameNameSelection = await vscode.window.showQuickPick(
["jak1", "jak2"], ["jak1", "jak2", "jak3"],
{ {
title: "Game?", title: "Game?",
}, },
@ -234,8 +241,10 @@ async function decompSpecificFile() {
} else { } else {
if (gameNameSelection == "jak1") { if (gameNameSelection == "jak1") {
gameName = GameName.Jak1; gameName = GameName.Jak1;
} else { } else if (gameNameSelection == "jak2") {
gameName = GameName.Jak2; gameName = GameName.Jak2;
} else if (gameNameSelection == "jak3") {
gameName = GameName.Jak3;
} }
} }
const validNames = await getValidObjectNames(gameNameSelection); const validNames = await getValidObjectNames(gameNameSelection);
@ -318,6 +327,7 @@ async function decompAllActiveFiles() {
), ),
); );
jak1ObjectNames = [...new Set(jak1ObjectNames)]; jak1ObjectNames = [...new Set(jak1ObjectNames)];
let jak2ObjectNames = truncateFileNameEndings( let jak2ObjectNames = truncateFileNameEndings(
getFileNamesFromUris(getUrisFromTabs(/.*jak2\/.*_ir2\.asm/)), getFileNamesFromUris(getUrisFromTabs(/.*jak2\/.*_ir2\.asm/)),
"_ir2.asm", "_ir2.asm",
@ -330,11 +340,23 @@ async function decompAllActiveFiles() {
); );
jak2ObjectNames = [...new Set(jak2ObjectNames)]; 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) { if (jak1ObjectNames.length > 0) {
const jak1Config = getDecompilerConfig(GameName.Jak1); const jak1Config = getDecompilerConfig(GameName.Jak1);
if (jak1Config === undefined) { if (jak1Config === undefined) {
await vscode.window.showErrorMessage( await vscode.window.showErrorMessage(
"OpenGOAL - Can't decompile no Jak 1 config selected", "OpenGOAL - Can't decompile, no Jak 1 config selected",
); );
return; return;
} }
@ -345,12 +367,22 @@ async function decompAllActiveFiles() {
const jak2Config = getDecompilerConfig(GameName.Jak2); const jak2Config = getDecompilerConfig(GameName.Jak2);
if (jak2Config === undefined) { if (jak2Config === undefined) {
await vscode.window.showErrorMessage( await vscode.window.showErrorMessage(
"OpenGOAL - Can't decompile no Jak 2 config selected", "OpenGOAL - Can't decompile, no Jak 2 config selected",
); );
return; return;
} }
await decompFiles(jak2Config, GameName.Jak2, jak2ObjectNames); 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() { function openManPage() {
@ -419,6 +451,8 @@ async function updateSourceFile() {
let gameName = "jak1"; let gameName = "jak1";
if (editor.document.uri.fsPath.includes("jak2")) { if (editor.document.uri.fsPath.includes("jak2")) {
gameName = "jak2"; gameName = "jak2";
} else if (editor.document.uri.fsPath.includes("jak3")) {
gameName = "jak3";
} }
const { stdout, stderr } = await execAsync( const { stdout, stderr } = await execAsync(
@ -463,6 +497,8 @@ async function updateReferenceTest() {
let gameName = "jak1"; let gameName = "jak1";
if (editor.document.uri.fsPath.includes("jak2")) { if (editor.document.uri.fsPath.includes("jak2")) {
gameName = "jak2"; gameName = "jak2";
} else if (editor.document.uri.fsPath.includes("jak3")) {
gameName = "jak3";
} }
const folderToSearch = vscode.Uri.joinPath( const folderToSearch = vscode.Uri.joinPath(
getProjectRoot(), getProjectRoot(),

View file

@ -103,6 +103,8 @@ async function preserveBlock() {
let gameName = "jak1"; let gameName = "jak1";
if (game === GameName.Jak2) { if (game === GameName.Jak2) {
gameName = "jak2"; gameName = "jak2";
} else if (game === GameName.Jak3) {
gameName = "jak3";
} }
const gsrcPath = await findFileInGoalSrc(projectRoot, gameName, fileName); const gsrcPath = await findFileInGoalSrc(projectRoot, gameName, fileName);
@ -437,6 +439,22 @@ async function genMethodStubs() {
return; 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() { export async function activateMiscDecompTools() {
getExtensionContext().subscriptions.push( getExtensionContext().subscriptions.push(
vscode.commands.registerCommand( vscode.commands.registerCommand(
@ -480,4 +498,10 @@ export async function activateMiscDecompTools() {
genMethodStubs, genMethodStubs,
), ),
); );
getExtensionContext().subscriptions.push(
vscode.commands.registerCommand(
"opengoal.decomp.misc.applyDecompilerSuggestions",
applyDecompilerSuggestions,
),
);
} }

View file

@ -21,13 +21,18 @@ export function getCastFileData(
if (gameName == GameName.Jak1) { if (gameName == GameName.Jak1) {
castFilePath = vscode.Uri.joinPath( castFilePath = vscode.Uri.joinPath(
projectRoot, projectRoot,
`decompiler/config/jak1/${config.jak2DecompConfigVersion}/${fileName}`, `decompiler/config/jak1/${config.jak1DecompConfigVersion}/${fileName}`,
).fsPath; ).fsPath;
} else if (gameName == GameName.Jak2) { } else if (gameName == GameName.Jak2) {
castFilePath = vscode.Uri.joinPath( castFilePath = vscode.Uri.joinPath(
projectRoot, projectRoot,
`decompiler/config/jak2/${config.jak2DecompConfigVersion}/${fileName}`, `decompiler/config/jak2/${config.jak2DecompConfigVersion}/${fileName}`,
).fsPath; ).fsPath;
} else if (gameName == GameName.Jak3) {
castFilePath = vscode.Uri.joinPath(
projectRoot,
`decompiler/config/jak3/${config.jak3DecompConfigVersion}/${fileName}`,
).fsPath;
} }
if (!existsSync(castFilePath)) { if (!existsSync(castFilePath)) {
return undefined; return undefined;
@ -59,7 +64,13 @@ export function getDecompilerConfigDirectory(
decompConfigPath = vscode.Uri.joinPath( decompConfigPath = vscode.Uri.joinPath(
projectRoot, projectRoot,
`decompiler/config/jak2/`, `decompiler/config/jak2/`,
getConfig().jak1DecompConfigVersion, getConfig().jak2DecompConfigVersion,
).fsPath;
} else if (gameName == GameName.Jak3) {
decompConfigPath = vscode.Uri.joinPath(
projectRoot,
`decompiler/config/jak3/`,
getConfig().jak3DecompConfigVersion,
).fsPath; ).fsPath;
} }
if (decompConfigPath === undefined || !existsSync(decompConfigPath)) { if (decompConfigPath === undefined || !existsSync(decompConfigPath)) {

View file

@ -6,6 +6,7 @@ import { getRecentFiles } from "../context";
export enum GameName { export enum GameName {
Jak1 = "jak1", Jak1 = "jak1",
Jak2 = "jak2", Jak2 = "jak2",
Jak3 = "jak3",
} }
const fileSwitchingAssoc = { const fileSwitchingAssoc = {
@ -51,6 +52,8 @@ export function determineGameFromPath(path: vscode.Uri): GameName | undefined {
return GameName.Jak1; return GameName.Jak1;
} else if (path.fsPath.includes("jak2")) { } else if (path.fsPath.includes("jak2")) {
return GameName.Jak2; return GameName.Jak2;
} else if (path.fsPath.includes("jak3")) {
return GameName.Jak3;
} }
return undefined; return undefined;
} }
@ -58,11 +61,13 @@ export function determineGameFromPath(path: vscode.Uri): GameName | undefined {
export function determineGameFromAllTypes( export function determineGameFromAllTypes(
path: vscode.Uri, path: vscode.Uri,
): GameName | undefined { ): GameName | undefined {
if (path.fsPath.includes("jak2")) { if (path.fsPath.includes("jak1")) {
return GameName.Jak2;
}
// jak 1 isn't in it's own folder sadly
return GameName.Jak1; return GameName.Jak1;
} else if (path.fsPath.includes("jak2")) {
return GameName.Jak2;
} else if (path.fsPath.includes("jak3")) {
return GameName.Jak3;
}
} }
export async function getDirectoriesInDir(dir: string) { export async function getDirectoriesInDir(dir: string) {