- C 50.5%
- Python 40.5%
- Assembly 5.3%
- Makefile 1.7%
- Linker Script 1.5%
- Other 0.5%
| .vscode | ||
| client | ||
| output | ||
| resources/videopatterns | ||
| server | ||
| toolchain | ||
| .gitignore | ||
| LICENSE | ||
| Makefile | ||
| README.md | ||
| requirements.txt | ||
Shell for N64
shn64 provides a python-based remote experimentation playground for Nintendo 64 (and soon™ the iQue Player) over USB for fast iteration of tests. It is inspired by m1n1.
The python client communicates with a server running on the target via flashcart USB. The server implements basic commands such as "read memory at address", "write memory at address", "execute at address" which can be scripted interactively on the client side. This enables rapid experimentation and testing for faster discovery of hardware details, as opposed to spinning up a new test ROM every time.
To use, open a terminal window in the root of the repository and, after installing the toolchain (see below), execute make run while your N64 is switched on and can receive a ROM over USB. For Everdrive, this means boot to the menu. On first run this will create a python virtual environment, install the required packages to run the client, and build the server ROM.
Supported Flashcarts (help wanted!)
- Everdrive X7
- Everdrive v3 with OS version >= 3.04
To run the environment you will need the following packages:
- make
- python3.10
- python3.10-pip
- python3.10-venv
Environment Builtins
The following names are exposed to the interpreter on session start:
DEVICE: TheExtDeviceinstance. Represents the device used to communicate with the target.PROXY: TheProxyinstance. This class contains all commands to issue transactions with the remote server.TOOLCHAIN_ROOT: The toolchain prefix. e.g.f"{TOOLCHAIN_ROOT}as"resolves a valid path to the assembler binary.SERVER_ELF: The file path to the server .elf file.reload: Function. Manually reloads the specified previously imported modules.LOG_SESSION: Function. Saves the current session history to a file.
Examples
# Dump RI Registers
from modules.bytebuffer import hexdump
mem = PROXY.read_mem(0xA4700000, 4, 0x20//4)
hexdump(mem)
# Allocate a buffer, write memory into the buffer, read it back and check equality.
with PROXY.malloc(256) as addr:
buf1 = bytes(i for i in range(256))
PROXY.write_mem(addr, 1, buf1)
buf2 = PROXY.read_mem(addr, 1, 256)
assert buf1 == buf2
# Assemble and run code on the target
with PROXY.malloc(0x20, align=0x20) as addr:
data = Assembler(TOOLCHAIN_ROOT).assemble(\
f"""
.set noreorder
.set noat
start:
addu $t0, $t1, $t2
jr $ra
nop
""", addr)
PROXY.write_mem(addr, 4, data)
res = PROXY.exec(addr)
assert res.t0 == res.t1 + res.t2
Project Structure
.venv(gitignored): Python 3 Virtual Environment Default Location..vscode: C/C++ Configuration for Visual Studio Code.client: The python interpreter that runs on the host and communicates with the server to deliver the environment. Python module imports are relative toclient.client.modules: Reusable utilities for use in experiments.
output: This is the default cwd of the interpreter, files will be opened relative to this directory.resources: Reusable resource files for use in experiments, such as texture images.server: The source for the program that will run on the external device.toolchain: Contains toolchain build tools.
Toolchain Information
We use a fork of glankk/n64 with rsp assembler support to provide gcc and binutils for both building the server and for the client to use.
There are two installation options:
- Download the prebuilt artifacts
- Build the toolchain from source
Downloading
Currently unsupported.
Building
To build the toolchain you will need the following packages installed:
build-essential pkg-config zlib1g-dev libexpat1-dev python3-dev make gcc g++ gcc-multilib libgmp-dev libmpfr-dev bison file gperf autoconf wget tar diffutils texinfo
Run build-toolchain.sh in the toolchain directory to install the toolchain to SHN64_TOOLCHAIN_INST defined in the environment.
Attribution
Server
- shn64 adapts portions of libdragon, as indicated in individual source files, licensed under The Unlicense.
- shn64 adapts portions of glankk's gdb stub for the Ocarina of Time Decompilation, as indicated in individual source files, licensed under the MIT License.
- shn64 adapts portions of musl-libc's stdio and math routines, as indicated in individual source files, licensed under the MIT License.
- shn64 embeds the Press Start 2P font, licensed under the SIL Open Font License.
Client
- shn64 adapts portions of m1n1's proxy client, licensed under the MIT License.
See requirements.txt for used python packages and their versions, managed by pip. All package versions are pinned to specific versions to ensure, as much as possible, a consistent operating environment between users.