mcdosbox-x/examples/ripterm_bezier.py
Ryan Malloy 170eba0843 Initial implementation of DOSBox-X MCP Server
MCP server for AI-assisted debugging of DOS binaries via GDB protocol.

Features:
- GDB remote protocol client for DOSBox-X debugging
- 16 debugging tools: launch, attach, breakpoint management,
  registers, memory read/write, disassemble, step, continue, etc.
- Docker container with DOSBox-X for consistent environment
- Support for DOS segment:offset addressing
- Comprehensive test suite (49 tests)

Primary use case: Reverse engineering the unpublished Bezier algorithm
in RIPTERM.EXE for the RIPscrip graphics protocol project.
2026-01-27 13:07:51 -07:00

157 lines
4.8 KiB
Python

#!/usr/bin/env python3
"""Example: Tracing the Bezier algorithm in RIPTERM.EXE
This script demonstrates how to use the DOSBox-X MCP server to trace
the unpublished Bezier curve algorithm in RIPTERM.EXE.
The goal is to:
1. Launch DOSBox-X with RIPTERM
2. Set breakpoints at suspected Bezier drawing code
3. Feed a test RIPscrip file with Bezier commands
4. Capture register/memory state at each point
5. Reconstruct the algorithm from the captured data
Prerequisites:
- RIPTERM.EXE in the ./dos directory
- A test RIP file with Bezier commands
- DOSBox-X MCP server running
Usage:
python examples/ripterm_bezier.py
Note: This is a conceptual example. The actual addresses would need to be
determined through static analysis (e.g., in Ghidra) first.
"""
import json
import time
from pathlib import Path
def trace_bezier():
"""Trace the Bezier algorithm execution."""
# These would be determined from Ghidra analysis
# Hypothetical addresses for RIPTERM's Bezier code
BEZIER_ENTRY = "1234:0100" # Where Bezier processing starts
DRAW_POINT = "1234:0200" # Where individual points are drawn
CALCULATE = "1234:0300" # The core calculation routine
print("=" * 60)
print("RIPTERM Bezier Algorithm Tracer")
print("=" * 60)
print()
# This would use the MCP tools via Claude or direct API
# For demonstration, we'll show the intended flow:
print("Step 1: Launch DOSBox-X with RIPTERM")
print(" launch('/path/to/dos/RIPTERM.EXE')")
print()
print("Step 2: Attach to GDB stub")
print(" attach('localhost', 1234)")
print()
print("Step 3: Set breakpoints at key addresses")
print(f" breakpoint_set('{BEZIER_ENTRY}') # Bezier entry")
print(f" breakpoint_set('{DRAW_POINT}') # Draw point")
print(f" breakpoint_set('{CALCULATE}') # Calculation")
print()
print("Step 4: Continue execution until breakpoint")
print(" continue_execution()")
print()
print("Step 5: When breakpoint hit, capture state:")
print("""
# Read registers
regs = registers()
print(f"AX={regs['ax']} BX={regs['bx']} CX={regs['cx']} DX={regs['dx']}")
# Read stack (parameters often passed on stack)
stack_data = stack(16)
# Read data segment (for global variables)
mem = memory_read("DS:0000", 256)
# Step through to see calculation
for i in range(100):
step()
regs = registers()
# Log coordinate values
print(f"Step {i}: X={regs['cx']} Y={regs['dx']}")
""")
print("Step 6: Analyze captured data to reconstruct algorithm")
print()
# Example of what the captured data might look like
example_trace = [
{"step": 0, "x": 100, "y": 50, "note": "Control point 1"},
{"step": 10, "x": 112, "y": 58, "note": "Interpolated"},
{"step": 20, "x": 125, "y": 65, "note": "Interpolated"},
{"step": 30, "x": 138, "y": 71, "note": "Interpolated"},
{"step": 40, "x": 150, "y": 75, "note": "Control point 2 region"},
{"step": 50, "x": 162, "y": 71, "note": "Curving back"},
{"step": 60, "x": 175, "y": 65, "note": "Interpolated"},
{"step": 70, "x": 188, "y": 58, "note": "Interpolated"},
{"step": 80, "x": 200, "y": 50, "note": "End point"},
]
print("Example trace output:")
print("-" * 40)
for point in example_trace:
print(f" Step {point['step']:3d}: ({point['x']:3d}, {point['y']:3d}) - {point['note']}")
print()
print("From this data, we could determine:")
print(" - Whether it uses De Casteljau's algorithm")
print(" - The number of subdivisions")
print(" - Fixed-point vs floating-point math")
print(" - Any optimizations or approximations")
def create_test_rip():
"""Create a simple RIP file to test Bezier drawing."""
# RIPscrip Level 0 Bezier command
# The format is: !|z<x1><y1><x2><y2><x3><y3><x4><y4>
# Using MegaNum encoding
test_rip = """!|
!|E
!|c0F
!|z00320064009600C800C8006400640032
"""
# This draws a Bezier curve with:
# Start: (50, 100)
# Control 1: (150, 200)
# Control 2: (200, 100)
# End: (100, 50)
test_file = Path("dos/test-bezier.RIP")
test_file.parent.mkdir(exist_ok=True)
test_file.write_text(test_rip)
print(f"Created test file: {test_file}")
return test_file
def main():
"""Main entry point."""
print()
trace_bezier()
print()
print("=" * 60)
print("To actually run this:")
print("1. Use Ghidra to find the real Bezier addresses in RIPTERM.EXE")
print("2. Start the DOSBox-X MCP server")
print("3. Use Claude to interactively debug with these tools")
print("=" * 60)
if __name__ == "__main__":
main()