diff --git a/README.md b/README.md
index 085d977..0c9c7a5 100644
--- a/README.md
+++ b/README.md
@@ -66,6 +66,7 @@ To start the emulator and begin debugging automatically:
"args": ["--dap"],
"stopOnEntry": true,
"cwd": "${workspaceFolder}",
+ "srcDirs": ["${workspaceFolder}/lib/src", ...],
"trace": true
}
```
@@ -75,6 +76,7 @@ To start the emulator and begin debugging automatically:
* `args`: Enter whatever arguments your emulator needs to enable DAP server.
* `stopOnEntry`: Set to `true` to halt at program start.
* `cwd`: Working directory.
+* `srcDirs`: Optional additional list of paths to lookup for source files
* `trace`: Enables DAP message logging for troubleshooting.
### Attach to a Running Emulator
@@ -142,6 +144,7 @@ for the pack is being received.
List of emulators supporting this variation of DAP:
* Emu
— The [X65 Computer](https://x65.zone/) Emulator.
+* Steckschwein
— The [Steckschwein](https://www.steckschwein.de/) Emulator.
If you know any other, please [create a PR][4] with an update to the list.
diff --git a/package.json b/package.json
index 05db837..2c9ac85 100644
--- a/package.json
+++ b/package.json
@@ -178,6 +178,14 @@
"type": "string",
"description": "Absolute path to the working directory.",
"default": "${cwd}"
+ },
+ "srcDirs": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "An additional list of lookup paths for source files - e.g. required if we step from main debug code into a subroutine of a library",
+ "default": false
}
}
},
@@ -203,6 +211,14 @@
"type": "boolean",
"description": "Run without debugging.",
"default": false
+ },
+ "srcDirs": {
+ "type": "array",
+ "items": {
+ "type": "string"
+ },
+ "description": "An additional list of lookup paths for source files - e.g. required if we step from main debug code into a subroutine of a library",
+ "default": false
}
}
}
diff --git a/src/cc65Debug.ts b/src/cc65Debug.ts
index 4590ded..7c8ad8a 100644
--- a/src/cc65Debug.ts
+++ b/src/cc65Debug.ts
@@ -12,6 +12,7 @@
*/
import { type ChildProcessWithoutNullStreams, spawn } from "node:child_process";
+import * as fs from "node:fs";
import * as path from "node:path";
import { Logger, LoggingDebugSession, TerminatedEvent, logger } from "@vscode/debugadapter";
import type { DebugProtocol } from "@vscode/debugprotocol";
@@ -52,6 +53,8 @@ interface IRequestArguments extends DebugProtocol.LaunchRequestArguments {
trace?: boolean;
/** run without debugging */
noDebug?: boolean;
+ /** An additional list of lookup paths for source files - e.g. required if we step from main debug code into a subroutine of a library */
+ srcDirs?: string[];
}
interface ILaunchRequestArguments extends IRequestArguments {
@@ -105,6 +108,11 @@ export class Cc65DebugSession extends LoggingDebugSession {
this.setDebuggerLinesStartAt1(true);
this.setDebuggerColumnsStartAt1(true);
+ const srcDirs: string[] = this._session.configuration.srcDirs || [];
+
+ this._debugPathBases = [
+ ...new Set([...this._debugPathBases, ...((srcDirs as string[]) ?? [])]),
+ ];
// make sure to 'Stop' the buffered logging if 'trace' is not set
logger.setup(
this._session.configuration.trace ? Logger.LogLevel.Verbose : Logger.LogLevel.Stop,
@@ -696,10 +704,14 @@ export class Cc65DebugSession extends LoggingDebugSession {
showUser: true,
});
}
-
+ const dbgFileBaseName = path.basename(sourceBase);
+ const dbgFileSize = fs.statSync(source.path).size;
const dbgFile = this._debugData?.file.find((file) => {
const filePath = `${path.posix.sep}${normalizePath(file.name)}`;
- return filePath.endsWith(`${path.posix.sep}${sourceBase}`);
+ return (
+ dbgFileSize === file.size &&
+ filePath.endsWith(`${path.posix.sep}${dbgFileBaseName}`)
+ );
});
if (!response.body) response.body = { breakpoints: [] };
@@ -717,7 +729,7 @@ export class Cc65DebugSession extends LoggingDebugSession {
}
// Store path base for later name reconstruction
- const fileBase = normalizePath(dbgFile.name).slice(0, -sourceBase.length);
+ const fileBase = sourceBase.slice(0, -normalizePath(dbgFile.name).length);
if (!this._debugPathBases.includes(fileBase)) this._debugPathBases.push(fileBase);
// map source lines to memory addresses
@@ -926,9 +938,15 @@ export class Cc65DebugSession extends LoggingDebugSession {
// --------------------------------------------------------------------
private dbgFile2workspace(dbgFile: DbgFile) {
const fileName = normalizePath(dbgFile.name);
- for (const base of this._debugPathBases) {
- if (fileName.startsWith(base)) {
- return fileName.slice(base.length);
+ // lookup relative to workspaceFolder
+ const workspaceFolder = normalizePath(
+ path.resolve(this._session.workspaceFolder?.uri.fsPath || "."),
+ );
+ // build path and do fs lookup
+ for (const pathBase of this._debugPathBases) {
+ const candidate = path.resolve(workspaceFolder, pathBase, fileName);
+ if (fs.existsSync(candidate) && fs.statSync(candidate).size === dbgFile.size) {
+ return normalizePath(path.relative(workspaceFolder, candidate));
}
}
}