PIF-NUS

The PIF-NUS (or PIF, or PIF(P)-NUS on PAL) manages multiple critical functions of the N64 console. It is a physical microchip found on the console's motherboard, which is based on the Sharp SM5 Microcontroller. It is not clear whether SGI or Nintendo intended this to stand for "Peripheral InterFace" or not. While the naming is unintuitive, the Peripheral (or Parallel) Interface is used to read/write to the game ROM and devices like the 64DD; whereas, the PIF handles the following:
 * Console startup and piracy protections
 * Stores the first 2 stages of the Initial Program Load (IPL) that is executed by the VR4300 CPU
 * Console reset button to avoid corrupting save game data
 * Controller and EEPROM read/write via JoyBus protocol

Internal ROM and RAM
Since PIF is based on the Sharp SM5 which is a programmable microcontroller, its logic is executed by a program that is burnt into an internal ROM, called PIF-SM5-ROM. This program is written for the SM5 4-bit core, and has been dumped via chip decapping. The jago85/UltraPIF_MCUproject on GitHub is a compatible implementation based on the STM32 architecture that can be inspected for further studying what PIF does in details. Everything described in this page is implemented by the means of this internal program.

Moreover, PIF contains a second internal ROM (1984 bytes) and a small RAM (64 bytes). These memories are usually referred to as PIF-ROM and PIF-RAM, but it is important not confuse this PIF-ROM with the previous PIF-SM5-ROM. Both PIF-ROM and PIF-RAM are memory mapped to the VR4300 address space via the SI interface in RCP (so each access actually requires a serial bus transmission and is thus quite slow).

The PIF-ROM contains the first two stages of code for the VR4300 boot process (IPL1 and IPL2) and is only memory mapped to VR4300 during the boot. After the boot process is finished, before jumping into the game code, the PIF locks the PIF-ROM for security reason, so that it cannot be accessed by VR4300 anymore. The PIF-ROM is slightly different between PAL and NTSC console: it actually hardcodes the region and communicate it to VR4300 during the boot via the PIF-RAM.

Dumping the PIF-ROM can be done via software thanks to a loophole: it is in fact possible to boot the console once, setup a hardware breakpoint at  via the MIPS COP0 Watch register, and then soft-reset the console; as soon as the boot resumes, the interrupt will trigger; a registered handler for that interrupt would then be able to read the contents of PIF-ROM that are now unlocked, and dump them somewhere (eg: into SRAM). Check the hcs64/pif_rom_dumper project on GitHub for an example of implementing this technique.

The PIF-RAM is always available to be accessed by VR4300 and is used to perform communication with the PIF. Normally, it is used as part of the Joybus protocol to communicate with controllers and EEPROMs.

Console startup

 * 1) PIF holds all of the console components in reset mode
 * 2) PIF starts communicating with the CIC inside the cartridge
 * 3) CIC sends 4 bits (nibble) including region encoding
 * 4) CIC sends 4 bit encrypted seed value
 * 5) CIC sends 4 bit checksum
 * 6) PIF checks that these are the expected values
 * 7) If the values don't match, the PIF stops the boot (same scenario if no cartridge is inserted)
 * 8) The user would generally reset using the button or power off
 * 9) Remove/Re-insert cartridge (or change games)
 * 10) Power on (go to step #1)
 * 11) PIF writes the encrypted seed value to the PIF-RAM at offset   (mapped at  )
 * 12) PIF releases the reset pin for the whole console
 * 13) The PIF (console) and CIC (cartridge) communication continues as long as the console is powered on
 * 14) If there is ever a failure in the data exchange the console will be reset.
 * 15) VR4300 starts running code from address   which is mapped to PIF ROM via SI interface
 * 16) IPL1 is now executed directly fetching opcodes from PIF-ROM.
 * 17) These instructions are executed in this very slow manner.
 * 18) Thankfully IPL1 is only 52 instructions + some looping.
 * 19) It performs some really basic hardware initialization.
 * 20) It then copy the rest of the PIF-ROM (IPL2) to the RSP IMEM. Notice that at this point RDRAM is not initialized yet, so it cannot be used. RSP IMEM is instead available without any initialization and is much faster than PIF ROM thanks to the parallel bus.
 * 21) Jump to RSP IMEM to execute IPL2
 * 22) IPL2 is executed by the VR4300 reading the instructions from RSP IMEM
 * 23) More general hardware initialization
 * 24) If it's determined to be a 64DD disk, it will jump to
 * 25) Load IPL3 from the cartridge ROM into the RSP DMEM
 * 26) Check the checksum of IPL3, using the checksum seed provided by CIC at the beginning.
 * 27) VR4300 tells the PIF that the PIF-ROM can now be locked
 * 28) Jump to RSP DMEM to execute IPL3
 * 29) IPL3 is executed by the VR4300 reading the instructions from the RSP DMEM.
 * 30) Initialize RDRAM
 * 31) Depending on reset type
 * 32) Power On: Invalidate VR4300 ICache & DCache
 * 33) Reset : Writeback VR4300 ICache & DCache
 * 34) Move IPL3 execution from DMEM to RDRAM
 * 35) DMA 1 MB of Game code to RDRAM
 * 36) Authenticate 1 MB of Game Program
 * 37) Reset RSP
 * 38) Clear Interrupts
 * 39) Clear IPL3 from DMEM
 * 40) Clear IPL2 from IMEM
 * 41) Jump to Game code in RDRAM

Console Reset
The reset process is driven by the PIF, which is connected to the physical reset button. The actual reset is done via a NMI to VR4300 which resets it by starting again the full boot process, but it is important to notice that RCP is not reset in any way. The boot code expects the RCP to be idle when the boot is initiated and is not guaranteed to work if the RCP is active in any way (DMAs in progress, RDP drawing triangles, RSP executing code, etc.), which means that it is up to the VR300 to stop issuing commands to the RCP and putting it in idle state before the reset is executed. To do so, VR4300 is given a forewarn that a reset is incoming via an interrupt (aptly called "pre-NMI") and is given grace time of 500ms before the actual NMI arrives.

This is the full sequence:
 * 1) User presses Console Reset button
 * 2) PIF reads the button state
 * 3) PIF toggles VR4300 Interrupt 2 (INT2) also known as "pre-NMI".
 * 4) This is the time and opportunity for the game to finish saving game data and stop issuing commands to RCP to avoid graphics/audio corruption and/or a hard freeze.
 * 5) PIF sends the RESET command to CIC (command  )
 * 6) CIC waits for 500ms (grace time)
 * 7) CIC acknowledges the RESET command to PIF by writing a 0 bit.
 * 8) PIF toggles VR4300 Non-Maskable Interrupt (NMI) which resets it.
 * 9) PIF also unlocks the internal PIF ROM so that the boot process can start executing IPL1.

Controller and EEPROM communication
In addition to managing the Joybus Protocol for connected hardware like controllers and connected accessory PAKs

Sharp SM5 4-bit Microcontrollers
The PIF and CIC (inside the cartridge) are both custom versions of Sharp branded SM5 4-bit microcontrollers. These microcontrollers were also used in the Game & Watch handheld games, so Nintendo already had developers that were familiar with them. While the core functionality of the PIF and CIC are generally understood, the microcontroller model is custom and therefore not well known.

There has been some effort to reverse engineer the PIF and CIC communication to ease the process for creating compatible flash carts. At least 2 projects went through the time effort and money to decap the chips and view the internals of to better understand what they are doing.

CIC
'''Disclaimer: All of the CIC actions described below have been done successfully as part of a University project. Some of the details are missing whether it was to avoid encouraging piracy, simply not required for the core of the paper or lost in the language translation (authors live in Germany) is unknown.''' The test modes of the CIC are available on most (all?) retail cartridges.

To Enable Test Mode(s)
Pulling TS:0 and/or TS:1 high before power on will place the SM5 controller in one of 3 test modes. (Which test modes and which pin states are unknown) It's also unclear if you can change between test modes while the unit is powered on.

The fourth state is standard usage with TS:0 and TS:1 tied to ground.

It's unknown how slowly you can clock the CIC.

In Test Mode
Which mode is still unclear but the following functionality is available.

Arbitrary Code Execution
Instructions can be set 1 nibble at a time on Port 5 pins, most instructions are 1 byte long so they must be entered 1 nibble at a time then toggle the clock line.

Halt Instruction
The Halt instruction is encoded as 0x77 which is nice because it doesn't matter which nibble you send first. This instruction also has a nice benefit of causing a clear external change, the TIO line defaults to the Clock signal but after the Halt instruction it stops outputting a clock signal.

Stop Instruction
The Stop instruction is encoded as 0x76 which will assist in determining if the high or low nibble should be input first. This instruction also stops the TIO clock upon execution, so we have a clear external indication of success.

Output Data
Port 2 of the CIC can be used to output either the AREG register or the Program Counter (PC), it's unclear at this time if the difference is achieved with different test modes or by modifying internal configuration registers.

NOTE: On power up Port 2 is configured for Input, an internal configuration register must be modified to make it output.

Load Constant into Accumulator LDX
The LDX instuction can be used to populate the AREG with a known value that can be checked on Port 2

Dumping the CIC code
This process is very confusing so it may take some experimentation to work out the exact steps and details, the original document tries to explain but it feels like some details are missing.

Jump Instructions are 2 bytes, the first nibble is the instruction and the following 12 bits are the destination address.

Being in test mode seems to have a side effect on this instruction, inputting only the Jump instruction followed by a zero nibble, the second byte is loaded from the ROM, which is an instruction but is treated as data. The Jump instruction is then executed and the PC can be viewed on Port 2, as well

PIF
The PIF handles a lot of very core functions in the console. While the PIF chip is clearly a custom part, it appears to be heavily based on the SM5K (4/5/6) series. The instruction set and features match closely.