Expand shared Sprinter MCP with managed launch, raw reads and key input
This commit is contained in:
@@ -22,7 +22,9 @@ async def probe(socket: str, source: str, foreign_id: int):
|
||||
names = {tool.name for tool in listed.tools}
|
||||
expected = {'session_status', 'where', 'read_registers', 'read_memory',
|
||||
'recent_events', 'set_line_breakpoint', 'clear_breakpoint',
|
||||
'claim_control', 'release_control'}
|
||||
'claim_control', 'release_control', 'list_shares',
|
||||
'read_share', 'read_vram', 'read_screen_pixels', 'screenshot',
|
||||
'read_program_memory', 'list_ports'}
|
||||
if not expected <= names:
|
||||
raise RuntimeError('Не хватает MCP-инструментов: ' + str(expected - names))
|
||||
|
||||
@@ -44,6 +46,33 @@ async def probe(socket: str, source: str, foreign_id: int):
|
||||
registers['registers']['PC'] != location['pc'] or \
|
||||
len(memory['hex']) != 8 or not events['events']:
|
||||
raise RuntimeError('Неполный C-снимок MCP: ' + repr((status, location, memory)))
|
||||
program = await call('read_program_memory', {
|
||||
'address': hex(0x10000 + location['pc']), 'length': 4})
|
||||
if program['hex'] != memory['hex'] or program['space'] != 'program':
|
||||
raise RuntimeError('Raw program и logical Z80 расходятся в main')
|
||||
ports = await call('list_ports')
|
||||
if ports['truncated'] or not any(':kbd:ms_naturl:' in item['tag']
|
||||
for item in ports['ports']):
|
||||
raise RuntimeError('Порты PC-клавиатуры не найдены: ' + repr(ports)[:500])
|
||||
|
||||
shares = await call('list_shares')
|
||||
vram = [item for item in shares['shares'] if 'vram' in item['tag']]
|
||||
if len(vram) != 1 or vram[0]['size'] < 4:
|
||||
raise RuntimeError('VRAM share не найден: ' + repr(shares))
|
||||
raw_vram = await call('read_vram', {'address': '0', 'length': 4})
|
||||
same_share = await call('read_share', {
|
||||
'tag': vram[0]['tag'], 'address': '0', 'length': 4})
|
||||
if len(raw_vram['hex']) != 8 or raw_vram['hex'] != same_share['hex']:
|
||||
raise RuntimeError('Чтение VRAM/share различается')
|
||||
pixels = await call('read_screen_pixels', {
|
||||
'x': 0, 'y': 0, 'width': 2, 'height': 2})
|
||||
if len(pixels['hex']) != 16 or not pixels['stale_frame']:
|
||||
raise RuntimeError('Неверный снимок пикселей: ' + repr(pixels))
|
||||
shot = await call('screenshot')
|
||||
snapshot = Path(shot['path'])
|
||||
if snapshot.suffix != '.png' or snapshot.stat().st_size != shot['size'] or \
|
||||
snapshot.read_bytes()[:8] != b'\x89PNG\r\n\x1a\n':
|
||||
raise RuntimeError('Снимок MAME не является PNG: ' + repr(shot))
|
||||
|
||||
own = await call('set_line_breakpoint', {'file': source, 'line': 62})
|
||||
foreign = await client.call_tool('clear_breakpoint', {'identifier': foreign_id})
|
||||
@@ -59,7 +88,9 @@ async def probe(socket: str, source: str, foreign_id: int):
|
||||
'build_id': status['build_id'], 'pc': location['pc'],
|
||||
'tools': len(names), 'foreign_point_rejected': True,
|
||||
'owned_point_for_cleanup': own['id'],
|
||||
'control_claim_release': True},
|
||||
'control_claim_release': True,
|
||||
'shares_pixels_png': True,
|
||||
'program_and_ports': True},
|
||||
ensure_ascii=False), flush=True)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user