press_down
Simulate pressing the DOWN button on a GameBoy via the MCP GameBoy Server, allowing precise control with customizable duration in frames for accurate emulation interactions.
Instructions
Press the DOWN button on the GameBoy
Input Schema
TableJSON Schema
| Name | Required | Description | Default |
|---|---|---|---|
| duration_frames | No | Number of frames to hold the button |
Implementation Reference
- src/tools.ts:21-37 (registration)Dynamic registration of all press_XXX tools including 'press_down' (for GameBoyButton.DOWN). Defines input schema for duration_frames and the execution handler function that calls emulatorService.pressButton(button, duration_frames) and returns the screen image.Object.values(GameBoyButton).forEach(button => { server.tool( `press_${button.toLowerCase()}`, `Press the ${button} button on the GameBoy`, { duration_frames: z.number().int().positive().optional().default(1).describe('Number of frames to hold the button').default(25) }, async ({ duration_frames }): Promise<CallToolResult> => { // Press the button using the service (advances one frame) emulatorService.pressButton(button, duration_frames); // Return the current screen using the service const screen = emulatorService.getScreen(); return { content: [screen] }; } ); });
- src/emulatorService.ts:72-80 (helper)EmulatorService.pressButton - delegate method called directly from the tool handler. Delegates to GameBoyEmulator.pressButton and returns screen.pressButton(button: GameBoyButton, durationFrames: number): ImageContent { log.debug(`Pressing button: ${button}`); if (!this.isRomLoaded()) { log.warn('Attempted to press button with no ROM loaded'); throw new Error('No ROM loaded'); } this.emulator.pressButton(button, durationFrames); // This advances one frame return this.getScreen(); }
- src/gameboy.ts:43-67 (helper)Core implementation in GameBoyEmulator.pressButton: maps DOWN to Gameboy.KEYMAP.DOWN, presses the key for durationFrames frames via serverboy library, advances extra frame.public pressButton(button: GameBoyButton, durationFrames: number = 1): void { if (!this.romLoaded) { throw new Error('No ROM loaded'); } // Map our button enum to serverboy's keymap const buttonMap: Record<GameBoyButton, number> = { [GameBoyButton.UP]: Gameboy.KEYMAP.UP, [GameBoyButton.DOWN]: Gameboy.KEYMAP.DOWN, [GameBoyButton.LEFT]: Gameboy.KEYMAP.LEFT, [GameBoyButton.RIGHT]: Gameboy.KEYMAP.RIGHT, [GameBoyButton.A]: Gameboy.KEYMAP.A, [GameBoyButton.B]: Gameboy.KEYMAP.B, [GameBoyButton.START]: Gameboy.KEYMAP.START, [GameBoyButton.SELECT]: Gameboy.KEYMAP.SELECT }; for (let i=0; i < durationFrames; i++) { this.gameboy.pressKeys([buttonMap[button]]); this.gameboy.doFrame(); } // for now: advance one frame so we dont "hold" the button all the time. this.gameboy.doFrame(); }
- src/server/server.ts:24-26 (registration)Invocation of registerGameBoyTools in createGameBoyServer, which registers the press_down tool.// Register GameBoy tools registerGameBoyTools(server, emulatorService); // Pass emulatorService
- src/tools.ts:25-27 (schema)Input schema for press_down tool: optional duration_frames (number of frames to hold button down).{ duration_frames: z.number().int().positive().optional().default(1).describe('Number of frames to hold the button').default(25) },