renderScreen
Convert the C64 emulator screen to ASCII art for visual debugging, using characters to represent colors and content without image files.
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:1577-1632 (handler)The handler function for the 'renderScreen' tool. Captures the VICE display pixels and palette, calculates luminance for each color, samples the display at scaled coordinates, and renders an ASCII art approximation using a customizable character set for shading.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:1571-1575 (schema)Zod input schema for the renderScreen tool, defining optional parameters for output dimensions and character set used in ASCII rendering.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: ' .:-=+*#%@')"), }),
- src/index.ts:1554-1633 (registration)Registration of the 'renderScreen' MCP tool using server.registerTool, including detailed description, input schema validation, and the complete inline handler implementation.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); } } );