Skip to main content
Glama
simen
by simen

readVicState

Retrieve and interpret VIC-II video chip state to understand Commodore 64 display configuration, including colors, graphics modes, memory locations, and raster position.

Instructions

Read the full VIC-II state with interpreted values.

Returns all VIC-II registers with semantic meaning:

  • Border and background colors (with names)

  • Graphics mode (text, bitmap, multicolor, etc.)

  • Screen and character memory locations

  • Scroll values

  • Raster position

  • Sprite enable bits

This is the high-level view of the video chip. Use for understanding display configuration.

Related tools: readScreen, readSprites, readMemory (for $D000-$D02E)

Input Schema

TableJSON Schema
NameRequiredDescriptionDefault

No arguments

Implementation Reference

  • The core handler function for the 'readVicState' tool. Registers the tool with MCP server and implements the logic: reads VIC-II registers, computes bank/video addresses, graphics mode, sprite visibility, formats colors, and returns structured state with hints.
    server.registerTool( "readVicState", { description: `Read the full VIC-II state with interpreted values. Returns all VIC-II registers with semantic meaning: - Border and background colors (with names) - Graphics mode (text, bitmap, multicolor, etc.) - Screen and character memory locations - Scroll values - Raster position - Sprite enable bits This is the high-level view of the video chip. Use for understanding display configuration. Related tools: readScreen, readSprites, readMemory (for $D000-$D02E)`, }, async () => { try { // Read all VIC registers $D000-$D02E (47 bytes) const vicData = await client.readMemory(0xd000, 0xd02e); // Read CIA2 for bank info const cia2Data = await client.readMemory(0xdd00, 0xdd00); const bankInfo = getVicBank(cia2Data[0]); const d011 = vicData[0x11]; const d016 = vicData[0x16]; const d018 = vicData[0x18]; const graphicsMode = getGraphicsMode(d011, d016); const videoAddrs = getVideoAddresses(d018, bankInfo.baseAddress); // Raster position (9-bit) const rasterLine = vicData[0x12] | ((d011 & 0x80) << 1); // Sprite enable and visibility check const spriteEnable = vicData[0x15]; const spriteXMsb = vicData[0x10]; const enabledSprites: number[] = []; const visibleSprites: number[] = []; for (let i = 0; i < 8; i++) { if (spriteEnable & (1 << i)) { enabledSprites.push(i); // Check visibility const xLow = vicData[i * 2]; const xHigh = (spriteXMsb & (1 << i)) ? 256 : 0; const x = xLow + xHigh; const y = vicData[i * 2 + 1]; const visibility = isSpriteVisible(x, y, true); if (visibility.visible) { visibleSprites.push(i); } } } // Display enable const displayEnabled = !!(d011 & 0x10); const response = { // Colors borderColor: getColorInfo(vicData[0x20]), backgroundColor: [ getColorInfo(vicData[0x21]), getColorInfo(vicData[0x22]), getColorInfo(vicData[0x23]), getColorInfo(vicData[0x24]), ], // Graphics mode graphicsMode: graphicsMode.mode, displayEnabled, bitmap: graphicsMode.bitmap, multicolor: graphicsMode.multicolor, extendedColor: graphicsMode.extendedColor, // Screen geometry rows: d011 & 0x08 ? 25 : 24, columns: d016 & 0x08 ? 40 : 38, scrollX: d016 & 0x07, scrollY: d011 & 0x07, // Memory setup vicBank: { bank: bankInfo.bank, baseAddress: { value: bankInfo.baseAddress, hex: `$${bankInfo.baseAddress.toString(16).padStart(4, "0")}`, }, }, screenAddress: { value: videoAddrs.screenAddress, hex: `$${videoAddrs.screenAddress.toString(16).padStart(4, "0")}`, }, charAddress: { value: videoAddrs.charAddress, hex: `$${videoAddrs.charAddress.toString(16).padStart(4, "0")}`, }, // Raster rasterLine, // Sprites summary spriteEnable: { value: spriteEnable, binary: spriteEnable.toString(2).padStart(8, "0"), enabledSprites, enabledCount: enabledSprites.length, visibleSprites, visibleCount: visibleSprites.length, }, // Sprite multicolor registers spriteMulticolor0: getColorInfo(vicData[0x25]), spriteMulticolor1: getColorInfo(vicData[0x26]), hint: !displayEnabled ? "Display is blanked (DEN=0) - screen shows border color only" : enabledSprites.length > 0 ? visibleSprites.length < enabledSprites.length ? `${graphicsMode.mode} mode, ${enabledSprites.length} sprite(s) enabled but only ${visibleSprites.length} visible. Use readSprites() for details.` : `${graphicsMode.mode} mode, ${enabledSprites.length} sprite(s) enabled and visible.` : `${graphicsMode.mode} mode, no sprites enabled.`, }; return formatResponse(response); } catch (error) { return formatError(error as ViceError); } } );
  • Key helper used by readVicState to parse VIC-II graphics mode from D011 and D016 registers.
    export function getGraphicsMode(d011: number, d016: number): { mode: string; bitmap: boolean; multicolor: boolean; extendedColor: boolean; } { const ecm = !!(d011 & 0x40); const bmm = !!(d011 & 0x20); const mcm = !!(d016 & 0x10); let mode = "standard text"; if (ecm && !bmm && !mcm) mode = "extended background color"; else if (!ecm && !bmm && mcm) mode = "multicolor text"; else if (!ecm && bmm && !mcm) mode = "standard bitmap"; else if (!ecm && bmm && mcm) mode = "multicolor bitmap"; else if (ecm) mode = "invalid (ECM + other modes)"; return { mode, bitmap: bmm, multicolor: mcm, extendedColor: ecm, }; }
  • Helper to compute VIC-II memory bank from CIA2 $DD00 port A value, used in readVicState.
    export function getVicBank(cia2PortA: number): { bank: number; baseAddress: number } { // CIA2 port A bits 0-1 (inverted) select the bank const bankBits = (~cia2PortA) & 0x03; return { bank: bankBits, baseAddress: bankBits * 0x4000, }; }

Latest Blog Posts

MCP directory API

We provide all the information about MCP servers via our MCP API.

curl -X GET 'https://glama.ai/api/mcp/v1/servers/simen/vice-mcp'

If you have feedback or need assistance with the MCP directory API, please join our Discord server