renderScreen
Convert the C64 emulator screen to ASCII art for visual debugging. Generates a character-based representation of display content using configurable width, height, and character sets.
Instructions
Render the current screen as ASCII art representation.
Creates a visual representation of the screen using ASCII characters to approximate the colors and content visible on the C64 display.
This is useful for quick visual debugging without image handling. For actual screen text, use readScreen instead.
Options:
width: Output width in characters (default: 80)
height: Output height in lines (default: 50)
charset: Character set to use for shading (default: " .:-=+*#%@")
Related tools: readScreen, screenshot, readVicState
Input Schema
| Name | Required | Description | Default |
|---|---|---|---|
| width | No | Output width in characters (default: 80) | |
| height | No | Output height in lines (default: 50) | |
| charset | No | Characters for shading from dark to light (default: ' .:-=+*#%@') |
Implementation Reference
- src/index.ts:1610-1664 (handler)Handler function that implements the renderScreen tool: fetches display buffer and palette from VICE, computes pixel luminance, scales and maps to ASCII characters for visual representation.try { const display = await client.getDisplay(); const palette = await client.getPalette(); const outputWidth = args.width || 80; const outputHeight = args.height || 50; const charset = args.charset || " .:-=+*#%@"; // Calculate luminance for each palette color const luminance = palette.map((c) => { // Standard luminance formula return 0.299 * c.r + 0.587 * c.g + 0.114 * c.b; }); // Sample the display and convert to ASCII const scaleX = display.innerWidth / outputWidth; const scaleY = display.innerHeight / outputHeight; const lines: string[] = []; for (let y = 0; y < outputHeight; y++) { let line = ""; for (let x = 0; x < outputWidth; x++) { // Sample pixel from display const srcX = Math.floor(display.offsetX + x * scaleX); const srcY = Math.floor(display.offsetY + y * scaleY); const pixelIndex = srcY * display.width + srcX; if (pixelIndex < display.pixels.length) { const colorIndex = display.pixels[pixelIndex]; const lum = colorIndex < luminance.length ? luminance[colorIndex] : 0; // Map luminance (0-255) to charset index const charIndex = Math.floor((lum / 256) * charset.length); line += charset[Math.min(charIndex, charset.length - 1)]; } else { line += " "; } } lines.push(line); } return formatResponse({ width: outputWidth, height: outputHeight, sourceWidth: display.innerWidth, sourceHeight: display.innerHeight, charset, render: lines.join("\n"), hint: `ASCII rendering of ${display.innerWidth}x${display.innerHeight} display scaled to ${outputWidth}x${outputHeight}`, }); } catch (error) { return formatError(error as ViceError); } }
- src/index.ts:1586-1665 (registration)Registers the renderScreen MCP tool with detailed description, Zod input schema for width/height/charset parameters, and references the handler function.server.registerTool( "renderScreen", { description: `Render the current screen as ASCII art representation. Creates a visual representation of the screen using ASCII characters to approximate the colors and content visible on the C64 display. This is useful for quick visual debugging without image handling. For actual screen text, use readScreen instead. Options: - width: Output width in characters (default: 80) - height: Output height in lines (default: 50) - charset: Character set to use for shading (default: " .:-=+*#%@") Related tools: readScreen, screenshot, readVicState`, inputSchema: z.object({ width: z.number().min(20).max(200).optional().describe("Output width in characters (default: 80)"), height: z.number().min(10).max(100).optional().describe("Output height in lines (default: 50)"), charset: z.string().optional().describe("Characters for shading from dark to light (default: ' .:-=+*#%@')"), }), }, async (args) => { try { const display = await client.getDisplay(); const palette = await client.getPalette(); const outputWidth = args.width || 80; const outputHeight = args.height || 50; const charset = args.charset || " .:-=+*#%@"; // Calculate luminance for each palette color const luminance = palette.map((c) => { // Standard luminance formula return 0.299 * c.r + 0.587 * c.g + 0.114 * c.b; }); // Sample the display and convert to ASCII const scaleX = display.innerWidth / outputWidth; const scaleY = display.innerHeight / outputHeight; const lines: string[] = []; for (let y = 0; y < outputHeight; y++) { let line = ""; for (let x = 0; x < outputWidth; x++) { // Sample pixel from display const srcX = Math.floor(display.offsetX + x * scaleX); const srcY = Math.floor(display.offsetY + y * scaleY); const pixelIndex = srcY * display.width + srcX; if (pixelIndex < display.pixels.length) { const colorIndex = display.pixels[pixelIndex]; const lum = colorIndex < luminance.length ? luminance[colorIndex] : 0; // Map luminance (0-255) to charset index const charIndex = Math.floor((lum / 256) * charset.length); line += charset[Math.min(charIndex, charset.length - 1)]; } else { line += " "; } } lines.push(line); } return formatResponse({ width: outputWidth, height: outputHeight, sourceWidth: display.innerWidth, sourceHeight: display.innerHeight, charset, render: lines.join("\n"), hint: `ASCII rendering of ${display.innerWidth}x${display.innerHeight} display scaled to ${outputWidth}x${outputHeight}`, }); } catch (error) { return formatError(error as ViceError); } } );
- src/index.ts:1603-1608 (schema)Zod schema for renderScreen tool inputs: optional width (20-200), height (10-100), charset string.inputSchema: z.object({ width: z.number().min(20).max(200).optional().describe("Output width in characters (default: 80)"), height: z.number().min(10).max(100).optional().describe("Output height in lines (default: 50)"), charset: z.string().optional().describe("Characters for shading from dark to light (default: ' .:-=+*#%@')"), }), },