Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
3 changes: 3 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,7 @@ To start the emulator and begin debugging automatically:
"args": ["--dap"],
"stopOnEntry": true,
"cwd": "${workspaceFolder}",
"srcDirs": ["${workspaceFolder}/lib/src", ...],
"trace": true
}
```
Expand All @@ -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
Expand Down Expand Up @@ -142,6 +144,7 @@ for the pack is being received.
List of emulators supporting this variation of DAP:

* Emu <img src="https://raw.githubusercontent.com/X65/emu/main/emu.gif" alt="Emu"> — The [X65 Computer](https://x65.zone/) Emulator.
* Steckschwein <img src="https://www.steckschwein.de/steckschwein32.png" alt="Steckschwein Emulator"> — The [Steckschwein](https://www.steckschwein.de/) Emulator.

If you know any other, please [create a PR][4] with an update to the list.

Expand Down
16 changes: 16 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -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
}
}
},
Expand All @@ -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
}
}
}
Expand Down
30 changes: 24 additions & 6 deletions src/cc65Debug.ts
Original file line number Diff line number Diff line change
Expand Up @@ -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";
Expand Down Expand Up @@ -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 {
Expand Down Expand Up @@ -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,
Expand Down Expand Up @@ -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: [] };
Expand All @@ -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
Expand Down Expand Up @@ -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));
}
}
}
Expand Down
Loading