Simon Willison’s Weblog

Subscribe

Wednesday, 10th September 2025

I Replaced Animal Crossing’s Dialogue with a Live LLM by Hacking GameCube Memory (via) Brilliant retro-gaming project by Josh Fonseca, who figured out how to run 2002 Game Cube Animal Crossing in the Dolphin Emulator such that dialog with the characters was instead generated by an LLM.

The key trick was running Python code that scanned the Game Cube memory every 10th of a second looking for instances of dialogue, then updated the memory in-place to inject new dialog.

The source code is in vuciv/animal-crossing-llm-mod on GitHub. I dumped it (via gitingest, ~40,000 tokens) into Claude Opus 4.1 and asked the following:

This interacts with Animal Crossing on the Game Cube. It uses an LLM to replace dialog in the game, but since an LLM takes a few seconds to run how does it spot when it should run a prompt and then pause the game while the prompt is running?

Claude pointed me to the watch_dialogue() function which implements the polling loop.

When it catches the dialogue screen opening it writes out this message instead:

loading_text = ".<Pause [0A]>.<Pause [0A]>.<Pause [0A]><Press A><Clear Text>"

Those <Pause [0A]> tokens cause the came to pause for a few moments before giving the user the option to <Press A> to continue. This gives time for the LLM prompt to execute and return new text which can then be written to the correct memory area for display.

Hacker News commenters spotted some fun prompts in the source code, including this prompt to set the scene:

You are a resident of a town run by Tom Nook. You are beginning to realize your mortgage is exploitative and the economy is unfair. Discuss this with the player and other villagers when appropriate.

And this sequence of prompts that slowly raise the agitation of the villagers about their economic situation over time.

The system actually uses two separate prompts - one to generate responses from characters and another which takes those responses and decorates them with Animal Crossing specific control codes to add pauses, character animations and other neat effects.

# 12:24 pm / python, ai, prompt-engineering, generative-ai, llms, anthropic, claude, claude-4

Claude API: Web fetch tool. New in the Claude API: if you pass the web-fetch-2025-09-10 beta header you can add {"type": "web_fetch_20250910", "name": "web_fetch", "max_uses": 5} to your "tools" list and Claude will gain the ability to fetch content from URLs as part of responding to your prompt.

What's particularly interesting here is their approach to safety for this feature:

Enabling the web fetch tool in environments where Claude processes untrusted input alongside sensitive data poses data exfiltration risks. We recommend only using this tool in trusted environments or when handling non-sensitive data.

To minimize exfiltration risks, Claude is not allowed to dynamically construct URLs. Claude can only fetch URLs that have been explicitly provided by the user or that come from previous web search or web fetch results. However, there is still residual risk that should be carefully considered when using this tool.

My first impression was that this looked like an interesting new twist on this kind of tool. Prompt injection exfiltration attacks are a risk with something like this because malicious instructions that sneak into the context might cause the LLM to send private data off to an arbitrary attacker's URL, as described by the lethal trifecta. But what if you could enforce, in the LLM harness itself, that only URLs from user prompts could be accessed in this way?

Unfortunately this isn't quite that smart. From later in that document:

For security reasons, the web fetch tool can only fetch URLs that have previously appeared in the conversation context. This includes:

  • URLs in user messages
  • URLs in client-side tool results
  • URLs from previous web search or web fetch results

The tool cannot fetch arbitrary URLs that Claude generates or URLs from container-based server tools (Code Execution, Bash, etc.).

Note that URLs in "user messages" are obeyed. That's a problem, because in many prompt-injection vulnerable applications it's those user messages (the JSON in the {"role": "user", "content": "..."} block) that often have untrusted content concatenated into them - or sometimes in the client-side tool results which are also allowed by this system!

Anthropic do provide a much stronger mechanism here: you can allow-list domains using the "allowed_domains": ["docs.example.com"] parameter.

Provided you use allowed_domains and restrict them to domains which absolutely cannot be used for exfiltrating data (which turns out to be a tricky proposition) it should be possible to safely build some really neat things on top of this new tool.

# 5:24 pm / apis, security, ai, prompt-injection, generative-ai, llms, claude, exfiltration-attacks, llm-tool-use, lethal-trifecta

2025 » September

MTWTFSS
1234567
891011121314
15161718192021
22232425262728
2930