HackMii

Notes from inside your Wii

HackMii header image 2

The weird and wonderful CIC

January 17th, 2010 by Segher · 29 Comments

I have been spending some time on reverse engineering the Nintendo CIC ROMs. The CIC is the “lockout” chip in NES/SNES/N64 cartridges, used to get an iron grip on the market prevent people from copying games. It was manufactured by Sharp and is likely one of their old “one-chip microcomputers”, used in calculators and TV remotes and the like. I couldn’t find a document describing the instruction set it uses (or its architecture!), so I made it all up (combining information from lots of sources: old datasheets, old patents, and the low-res die photographs).

The N64 chips are different, and I haven’t seen a ROM dump of those yet, so all of the following is NES/SNES only.

There is one chip inside the console, and one in every cartridge; the code inside the chip decides what to do based on a pin strap (the console one will be the “lock”, and the cartridge one will be the “key”). The two chips run off the same clock, and they run the same code, so they run in lockstep (sometimes they execute different codepaths, but the code is careful to take the same number of cycles on both paths in these cases). The chips communicate over two wires, one from key to lock, one from lock to key. Both chips calculate what bits they will send, and what the other guy should send; if what they receive is not the same as what they should have received, they panic, and the lock chip resets the console.

Here is the pinout of the CIC:

              +------------------+
 DATA_OUT <-- | 1 P0.0    +5V 16 |
  DATA_IN --> | 2 P0.1        15 |  ?
     SEED --> | 3 P0.2        14 |  ?
LOCK/-KEY --> | 4 P0.3        13 |  ?
              | 5 Xout   P1.3 12 | <-- RESET_SPEED_B
              | 6 Xin    P1.2 11 | <-- RESET_SPEED_A
              | 7 RESET  P1.1 10 | --> SLAVE_CIC_RESET
              | 8 GND    P1.0  9 | --> -HOST_RESET
              +------------------+

The LOCK/-KEY pin is the strap pin I talked about above. The SEED pin has a capacitor connected to it; the discharge time of that is supposedly somewhat random, the lock chip times it and uses that as a random generator, to decide which of 16 possible streams to generate. It tells the key chip which one it chose.

The lock chip can reset the key chip (pin 10 on the lock is wired to pin 7 on the key), and it can reset the console. The RESET_SPEED pins are used on the 3195 to decide at what speed to “blink” the reset line (it’s connected to a LED as well): about 0.4s, 0.6s, 0.8s, 1.0s each of on/off.

There are dumps of the ROMs here, here, and here. All credits for doing these go to neviksti; thanks!

All the bits in those dumps are inverted (0 vs. 1); if you want to play along with the disassembler I’ll give a link to in a second, you’ll need to fix that; also, that third ROM is 768 bytes, which I don’t handle in my little conversion script, so you’ll need to remove the extra columns (they are empty anyway). Or enhance the script if you want to.

Okay then, here is that disassembler. Usage should be self-explanatory.

This ancient CPU looks mighty strange to modern eyes. Let me try to explain the architecture:

First, it is a 4-bit CPU. Yessir. It has an accumulator register, A, and a secondary register, X, both 4 bits. All RAM accesses are done via a single pointer register B, which is 6 bits; the CIC chip only has 32 nybbles of RAM though. There is also a carry flag, C.

Then, there is the process counter, PC. It is 10 bits, but there are only 512 bytes of ROM (except on the 3195, it has 768). The ROM is divided into banks of 128 bytes. When the CPU increments PC, it never touches the bank number.

Well, “increments”. To save chip area, they didn’t use a binary counter, but a polynomial counter; “incrementing” works by shifting the PC by one bit to the right, and setting the the top bit to 1 if and only if the bottom two bits were the same.

There are no conditional branch instructions; instead, various instructions can skip the next instruction if some condition is true (the instruction still takes time, it just doesn’t do anything). Oh, all instructions take one cycle; except for the two byte instructions, which take two cycles.

Finally, there is a four entry stack for the PC; it’s not in RAM, it is separate.

Now the instruction set:

"skip" means "do not execute next instruction"
"M" means "the RAM nybble addressed by B"
"BL" means "the low four bits of B"
"BM" means "the high two bits of B"
"PN" means "I/O port number BL"
"x.y" means "bit y of x"

00+N  adi N     "add immediate", A := A + N, skip if overflow   (00 is nop)
10+N  skai N    "skip acc immediate", skip if A = N
20+N  lbli N    "load B low immediate", BL := N
30+N  ldi N     "load immediate", A := N

40    l         "load", A := M
41    x         "exchange", swap A with M
42    xi        "exchange and increment", swap A with M, increment BL, skip if overflow
43    xd        "exchange and decrement", swap A with M, decrement BL, skip if underflow
44    nega      "negate acc", A := -A (two's complement)
46    out       "output", PN := A
47    out0      "output zero", PN := 0
48    sc        "set carry", C := 1
49    rc        "reset carry", C := 0
4a    s         "store", M := A
4c    rit       "return", pop PC from stack
4d    ritsk     "return and skip", pop PC from stack, skip
52    li        "load and increment", A := M, increment BL, skip if overflow
54    coma      "complement acc", A := ~A (ones' complement)
55    in        "input", A := PN
57    xal       "exchange acc and low", swap A with BL
5c    lxa       "load X with acc", X := A
5d    xax       "exchange X and acc", swap X with A
5e     ?        SPECIAL MYSTERY INSTRUCTION

60+N  skm N     "skip memory", skip if M.N = 1
64+N  ska N     "skip acc", skip if A.N = 1
68+N  rm N      "reset memory", M.N := 0
6c+N  sm N      "set memory", M.N := 1

70    ad        "add", A := A + M
72    adc       "add with carry", A := A + M + C
73    adcsk     "add with carry and skip", A := A + M + C, skip if overflow

74+N  lbmi N    "load B high immediate", BM := N

78+N NN  tl NNN    "transfer long", PC := NNN
7c+N NN  tml NNN   "transfer module long", push PC+2, PC := NNN
80+NN    t NN      "transfer", low bits of PC := NN

It would seem that on the 3195, the sc and rc instructions are swapped, as are the coma and nega instructions.

If you look at the code in the ROMs, you’ll notice something strange with the ldi instructions: sometimes it runs two in a row. Descriptions for similar CPUs say that if you have two or more ldi instructions in a row, all but the first are skipped. The code still doesn’t make sense then; I suspect that this CPU does this skip only if some condition that I do not know yet is true.

This architecture is quite different from what we are used to today, and so it requires quite different programs; I’ll leave it to you to discover all the intricacies yourself though, it’s more fun that way!

I put a commented disassembly of these ROMs here. Some of that is a work in progress.

I hope you all find this as fascinating as I did!

[edit: fixed op 52 "li" description]

Tags: Other consoles

29 responses so far ↓

  • 1 Mike // Jan 17, 2010 at 10:29 pm

    this is pretty cool, i wouldn’t know how to mess around with this, but its cool to read this if i ever can get into it

  • 2 SquidMan // Jan 17, 2010 at 10:38 pm

    *brain fries*
    Too old and small to understand for me. At least someone is working on reversing this crazy thing, finally. Maybe after 25 years, it’ll finally be understood properly :P

  • 3 Ibrahim Awwal // Jan 18, 2010 at 12:58 am

    Wow, that’s truly bizarre. A very interesting read.

    I don’t get what you mean about the PC though. If it shifts right, that means it’s going down, correct? And if the PC started at 0000000001 or 0000000010 to give an example, I don’t see why it wouldn’t just go to 0 and then get stuck? How does program execution work then?

  • 4 Ibrahim Awwal // Jan 18, 2010 at 1:00 am

    Oh, never mind. I thought you said if the bottom two bits were 1. Now I can see that once the PC is 0, it would then become 1000000000 and then move down. But that still seems very strange… overall it seems like this architecture requires a LOT of mental juggling to program it.

  • 5 Segher // Jan 18, 2010 at 1:08 am

    Ibrahim: yeah, it goes 00->40-> 60 -> 70 etc.
    If it starts at 7f, it gets stuck; there usually is a “t 0″ instruction at 7f, I think the assembler did that, it usually is just as bad to jump to 0 in the current page (it’s pretty much just a random jump) as it is to get stuck.

    It doesn’t require much juggling to program it as far as I can see, you use a symbolic assembler anyway. You only need to be careful when you cross banks, but we have similar gotchas on modern systems as well (esp. in firmware etc.).

  • 6 tech3475 // Jan 18, 2010 at 3:10 am

    I didn’t think 4bit CPUs existed since the Intel 4004 era.

    Thanks for posting this, I always find these an interesting read….even if I don’t understand half of it.

  • 7 DCX2 // Jan 18, 2010 at 7:24 am

    Yes, thanks Segher, that made for a nice breakfast. ^_^

  • 8 Muzer // Jan 18, 2010 at 10:15 am

    I’ve heard lots of theories about this but haven’t seen anyone do it – if you cut the pin to reset on the SNES chip will it allow all games, even SMRPG, to work? I’ve seen loads of theoretical solutions to get around it, but nobody actually trying anything.

  • 9 tech3475 // Jan 18, 2010 at 1:22 pm

    I know there is a trick for the 10NES (the version in the NES) chip:
    http://en.wikipedia.org/wiki/10NES#Circumvention

  • 10 Muzer // Jan 19, 2010 at 6:23 am

    Yes – that works on the SNES but some games (eg SMRPG) detect and refuse to work if you’ve done it.

  • 11 nuvalo // Jan 20, 2010 at 8:03 am

    Great work, it is fascinating how these CIC chips work.

    Muzer, SMRPG (and some other snes games) has some other software region lockout. That means that they can detect things like the cpu speed and the region of your console, and won’t work.

    SMRPG also does not use a CIC chip. Instead of that, the SA1 chip is in charge of region locks. That chip won’t let the game boot if it detects that the snes cic chip isn’t present. Here there is a mod for the SA1 chip wich will let you play SMRPG on any snes:

    http://img.photobucket.com/albums/v204/retroyoda/MarioRPGMod.jpg

    You have to unsolder the pin 127 and solder it to a 5V source. Then it will work.

  • 12 PimpKittah // Jan 20, 2010 at 2:41 pm

    First nice write up on the CIC, but i dont see anything about region identification anywhere or did i miss it? the CIC chip for PAL, NTSC, NTSC-J and other “odd regions” like the Matelco releases have different type of CIC chips inside of them, also due to some “ODD” maldesign in hw some nintendo games wont play on other region units even if the CIC is bypassed due to some hardware change in the PPU or CPU (JOUST is one of these games you cant make US one run on a PAL version or vise versa not related to the CIC) the NES systems had a lots of mysteries due to poor construction.

  • 13 jamesg // Jan 20, 2010 at 5:00 pm

    I had a UK SNES and could only play US and Jap carts with a Datel adapter. It allowed two carts to be plugged in at once (target game and a UK game to bypass the region check).

    I guess it must have split power and gnd to both carts and routed the key/lock signals to the UK cart only.

  • 14 Phredreeke // Jan 21, 2010 at 3:04 am

    That’s because PAL runs at 50hz, while NTSC runs at 60hz, and the NES units are locked to a specific frequency. Most of the time it just means PAL games run 20% faster on NTSC, and NTSC games running 17% slower on PAL, but sometimes games rely a bit too much on the video refresh rate. In particular, on PAL units the system has 20% more time to update a frame. A PAL game taking advantage of this extra time will finish in the next frame, then wait for sync, causing the game to update one frame every two frames, making the game to run 40% slower on NTSC units.

  • 15 jpx92681 // Jan 21, 2010 at 9:00 pm

    wow great! where are stored the saves in those cartridges.. ? i have always had that question… also by reading your article an old memory came to my mind, like 15 tears ago i saw a guy with a nes connected to a diskette drive… he ran the games from there that was awesome, thinking about that i realize that maybe that system bios or firmware were somehow replaced or updated to load the stuff from the diskette drive.

    if we could dive into that would be really great for me. let me know.

  • 16 PimpKittah // Jan 22, 2010 at 5:22 am

    jpx92681: games with save feature have builtin RAM (and battery to power it) to save data. Floppy hacks are actually NES floppy addon moddifications that where widely available in Japan officially but not much Official floppy addons had special type of floppy readers and floppys to prevent piracy.

  • 17 jpx92681 // Jan 22, 2010 at 12:49 pm

    PimpKittah/ ah ok.. wow officially in japan that is news for me .. umm very weird that i actually saw this hack here in southamerica, maybe they brought it from there or something..

  • 18 Masyanya // Jan 27, 2010 at 2:02 am

    To Segher.
    Hmmmm…. May i have… some qwestions?
    1. Where CARRY flag is placed? i mean, -
    SC ; Set CARRY flag
    ADC ; <– CARRY Flag is cleared after this command, or NOT?
    ; Which COMMNDS clear CARRY Flag and which NOT.
    2.0 B.5 "Overflow Bit". Hmmmm… Is B.5 also a CARRY Bit? Or B.5 used only AS MEMORY pointer "Overflow checker" BIT?
    2.1 Then B.5 is CLEAR or SET…?

    LBMI 0
    LBLI 15
    XI ;<- Is B.5 "SET" and SCIP processed? …or scip processed only then BM=1, BL=15 and we have another MEMORY count,(use XI, LI etc.).
    NOP;<-Is B.5 Cleared?

    2.2 About "B" Memory POINTER Increments/Decrements.
    For sample:
    LBMI 0 ;BM=0
    LBLI f ;BL=f
    XI ; AM, BL=BL+1 (After this COMMAND BL=0 and BM=1 or BL=0 and BM=2 or BL=0 and BM=0)

  • 19 Segher // Feb 9, 2010 at 3:09 am

    Masyanya:

    – Only “sc” and “rc” modify the carry flag, no other instructions do.

    – I have no idea where you get this “B.5″ from. Oh wait, you mean the high bit of BM. This particular CPU does not have enough RAM for that bit to do anything at all. It is not an overflow bit.

    – “xi” increases BL only, not BM, so the “skip if overflow” skips if BL changed from 15 to 0.

    – In your last example, you end up with BM=BL=0.

    Does that explain things to you?

  • 20 Masyanya // Feb 16, 2010 at 1:38 pm

    …not so…
    Hmmmm, …thanks.

    Please help me correct instructions SET, if you have some free time…

  • 21 Masyanya // Feb 16, 2010 at 1:39 pm

    hire instructin set image: http://mediapix.ru/pics/c6d67494dcb5a593c120afce7b7fefc3.gif

  • 22 WiiMAnWB // Feb 19, 2010 at 8:47 am

    http://emu-docs.org/Super%20NES/Cartridges/sfcdev2.php

    this is everything about the crc chip you need to know.

  • 23 Masyanya // Feb 24, 2010 at 12:54 am

    WiiMAnWB… :( What what “CRC chip”?
    Whats a f..king crap you route? On this link about CIC only few strings, and all of that already writen on top of this topic.
    In this case i can posts this: http://gbx.ru/index.php?showtopic=47624&hl=
    Nothing more comments…

    … “Segher” GREAT MAN. He make disassembled CIC FIRMWARE, and instructions set for this chip, but not all instructions fully undestanded for me…
    I’m build reversed CIC 6113 (Used ATMEL 8bit AVR core), based on this disassembed Firmware, original 6113 and my revesion work same, but no equal, and i need some corrections in instructions set to finish reversion… and I asks Segher spent some more time to correct my instructions set… if he can… /*be ashamed*/

  • 24 james // Mar 27, 2010 at 4:22 am

    hey can you clarify a couple of things

    all instructions are 1 cycle except $78 and $7C because they are two bytes?

    if the skip condition is false does it takes 1 cycle for the “skip instruction” plus the next instructions cycles?

    if the skip condition is true does it use 2 cycles? one for the “skip instruction” and the other “nop”?

  • 25 Segher // Mar 28, 2010 at 10:30 am

    james:

    Yes, 78..7f take two cycles because they are two bytes long; the CPU fetches one instruction byte per cycle.

    If an insn is skipped, it is still fetched. So it still takes a cycle; it isn’t executed though.

    You can look at the emulator in my git repo (dis-cic.git), it is cycle-exact as far as I know (it is for the various NES CICs at least).

  • 26 james // Mar 31, 2010 at 3:11 pm

    thanks segher that helps me a lot :)

    i know lbli sets the low nibble of the ram pointer does lbli also set the port number? it seems too if it doesn’t how does the port number get setup?

    what do you mean when you say two’s or one’s complement?

    when you say exchange/swap do you mean trade both ways?

    i found an error up top “set emmory”
    thanks again for helping me out

  • 27 Segher // Apr 2, 2010 at 6:58 pm

    > i know lbli sets the low nibble of the ram pointer does lbli also set the port number?

    From the big table:
    46 out “output”, PN := A
    “PN” means “I/O port number BL”

    So yes.

    > what do you mean when you say two’s or one’s complement?

    The standard stuff. I suppose even wikipedia will give you the correct answer.

    > when you say exchange/swap do you mean trade both ways?

    I suppose so, “trade both ways” isn’t exactly clear to me.

    > i found an error up top “set emmory”

    Fixed, thanks.

    > thanks again for helping me out

    My pleasure. Please note that the instruction table shows *exactly* what the insns do; also, you can look at my emulator if you aren’t sure.

  • 28 SNES Super CIC SNES Switchless Mod! - ModControl.Com - GermanysNr1MultiConsoleSceneSource // Jul 5, 2010 at 2:28 am

    [...] [...]

  • 29 A small recap, part 2 » project sd2snes // Aug 15, 2011 at 10:55 pm

    [...] Segher reverse engineered the SNES CIC and published the disassembled ROM dump of the D411 (US/JP CIC). I figured out the seeds of the D413 (EU CIC) – just one nibble was changed – and made a PIC based CIC replacement with automatic region fallback. sd2snes now worked on any unmodified SNES. (Also a pendant was later created to replace the original CIC in the console itself – with additional features like switchless 50/60Hz switching. See the SuperCIC page.) [...]

You must log in to post a comment.