Skip to content

Latest commit

 

History

History
144 lines (110 loc) · 6.16 KB

README.md

File metadata and controls

144 lines (110 loc) · 6.16 KB

r64

Goals

r64 is an abbreviation of Rust 64 which is an abbreviation of Rust Nintendo 64 which loosely translates to Nintendo 64 of Rust which can be interpreted as Nintendo 64 emulator written using the Rust programming language..

I wanted to brush up on my Rust skills, and I figured that a good way to do that would be to start a project that relied heavily on the use of Rust's systems programming concepts. Rather than putting Rust on hardware (which I will do at some point in the near future), I decided to use Rust to make hardware. I've written a 6502 emulator in the context of the NES in the past, so I wanted something a bit more challenging this time around. N64 played a huge role in my childhood, so it seemed like a logical choice.

This emulator has no goals for dynamic recompilation, cycle accuracy, or constraints for timing. Hence, it is a verbose and unoptimized Nintendo 64 emulator. My goal is, quite simply, to boot Super Mario 64 and see a wireframe of the rendered polygons - no textures, shading, or fancyness. If I get to this point, I may throw in audio emulation, and from there work my way towards a functional RCP.


Progress

Currently, the VR4300i CPU has been structured and can print the instructions that it is executing. Some of the core opcodes are implemented (special, load/store, jump/branch), others have yet to be looked at. If the CPU encounters an opcode that it can't execute, the unimplemented!() macro will be called, subsequently panicking the program.

Backends for nop RCP components are currently being implemented. Step 1 is to get the CPU executing properly, then more work will be done on graphics.

Component Status
CPU0 In Progress
TLB Not Implemented
CP0 In Progress
CP1/FPU Not Implemented
RCP In Progress
Audio Not Implemented
PIF Not Implemented

Usage

Build

Build the emulator as you would any other program in Rust.

cargo build

Run

An N64 ROM (.n64) and PIF ROM (.bin) are required to boot the emulator. The PIF ROM image can be obtained by searching for the SHA1 of the IPL 1.0 NTSC PIF ROM image, which is 9174eadc0f0ea2654c95fd941406ab46b9dc9bdd .

cargo run /path/to/rom.n64 /path/to/pifrom.bin

Once the program is launched, it will enter a REPL. The following commands can be provided after prompt.

Command Description
"step" / "s" Performs a step into the next CPU instruction and executes it.
"print" / "p" Prints the contents of the GPRs, CP0's registers, as well as the special registers.

Pressing enter is equivelent to the step command.

Example output is below.

0x9fc00000: (0x3c093400) lui t1, r0, 0x3400
> 
0x9fc00004: (0x40896000) mtc0 t4, t1, a0
> 
0x9fc00008: (0x3c090006) lui t1, r0, 0x6
> p
00 (r0): 0x0000000000000000 01 (at): 0x0000000000000000 
02 (v0): 0x0000000000000000 03 (v1): 0x0000000000000000 
04 (a0): 0x0000000000000000 05 (a1): 0x0000000000000000 
06 (a2): 0x0000000000000000 07 (a3): 0x0000000000000000 
08 (t0): 0x0000000000000000 09 (t1): 0x0000000000060000 
10 (t2): 0x0000000000000000 11 (t3): 0x0000000000000000 
12 (t4): 0x0000000000000000 13 (t5): 0x0000000000000000 
14 (t6): 0x0000000000000000 15 (t7): 0x0000000000000000 
16 (s0): 0x0000000000000000 17 (s1): 0x0000000000000000 
18 (s2): 0x0000000000000000 19 (s3): 0x0000000000000000 
20 (s4): 0x0000000000000000 21 (s5): 0x0000000000000000 
22 (s6): 0x0000000000000000 23 (s7): 0x0000000000000000 
24 (t8): 0x0000000000000000 25 (t9): 0x0000000000000000 
26 (k0): 0x0000000000000000 27 (k1): 0x0000000000000000 
28 (gp): 0x0000000000000000 29 (sp): 0x0000000000000000 
30 (s8): 0x0000000000000000 31 (ra): 0x0000000000000000 
> 
0x9fc0000c: (0x3529e463) ori t1, t1, 0xe463
> 
0x9fc00010: (0x40898000) mtc0 s0, t1, a0
> 
0x9fc00014: (0x3c08a404) lui t0, r0, 0xa404
> 
0x9fc00018: (0x8d080010) lw t0, 16(t0)
> p
00 (r0): 0x0000000000000000 01 (at): 0x0000000000000000 
02 (v0): 0x0000000000000000 03 (v1): 0x0000000000000000 
04 (a0): 0x0000000000000000 05 (a1): 0x0000000000000000 
06 (a2): 0x0000000000000000 07 (a3): 0x0000000000000000 
08 (t0): 0x0000000000000000 09 (t1): 0x000000000006E463 
10 (t2): 0x0000000000000000 11 (t3): 0x0000000000000000 
12 (t4): 0x0000000000000000 13 (t5): 0x0000000000000000 
14 (t6): 0x0000000000000000 15 (t7): 0x0000000000000000 
16 (s0): 0x0000000000000000 17 (s1): 0x0000000000000000 
18 (s2): 0x0000000000000000 19 (s3): 0x0000000000000000 
20 (s4): 0x0000000000000000 21 (s5): 0x0000000000000000 
22 (s6): 0x0000000000000000 23 (s7): 0x0000000000000000 
24 (t8): 0x0000000000000000 25 (t9): 0x0000000000000000 
26 (k0): 0x0000000000000000 27 (k1): 0x0000000000000000 
28 (gp): 0x0000000000000000 29 (sp): 0x0000000000000000 
30 (s8): 0x0000000000000000 31 (ra): 0x0000000000000000 
> 
0x9fc0001c: (0x31080001) andi t0, t0, 0x1
> 
0x9fc00020: (0x5100fffd) beql r0, t0, -3

> 
0xffffffff9fc00014: (0x3c08a404) lui t0, r0, 0xa404
> 
0xffffffff9fc00018: (0x8d080010) lw t0, 16(t0)
> 
0xffffffff9fc0001c: (0x31080001) andi t0, t0, 0x1
> 
0xffffffff9fc00020: (0x5100fffd) beql r0, t0, -3

Resources

vr4300i - Invaluable information about the main CPU.

cen64 - Great resource for the N64 memory map structure as well as the implementation of RCP behaviors.

rustendo64 - Good resource for the basic structure of an N64 emulator written in Rust.

n64dev - Lots of (not very organized) documentation about various aspects of the N64 hardware.

n64js - Awesome resource for stepping through N64 code and viewing change in system state.


License

This repo exists under the MIT license.

If you find this project useful, let me know via email or Twitter! (links on my GitHub account page)