NES CIC Lockout Chip

Wikis > Projects > NES CIC Lockout Chip

The NES lockout chip, known commonly as the CIC (Checking IC(Integrated Circuit)), was an IC found on NES game cartridges and consoles which served to prevent piracy and strengthen Nintendo’s iron grip on its illegal game monopoly. If no valid CIC chip is present on a game cartridge, or if the game’s contacts were dirty, the console would reset periodically every second indicating communication with the CIC was lost. During the course of the NES’s life, many manufacturers found horrible ways of circumventing the CIC with charge pumps and other hideous circuitry – but one company, Tengen, managed to reverse engineer the CIC algorithm.

None of the information and work presented here would be possible without Segher’s amazing work, found here. Also, a huge thanks to Infinite NES Lives for answering so many of questions about the CIC.

Development

This wiki is tied to two projects I am working on:

How It Works

The CIC in the console and the cartridge are identical. Pin 4 set to 0V identifies the CIC as in a cartridge (key mode). Pin 4 set to 5V identifies the CIC as in the console (lock mode). The two chips execute the same code and are clocked 4MHz signal. They communicate to each other over two wires; each calculating what the other should be sending. If the input differs from the calculation, the chip lockouts the cartridge and resets the console causing the user to blow in the cartridge.

                 ----_----
 Data Out 01 <-x|P0.0  Vcc|--- 16 +5V
 Data In  02 x->|P0.1 P2.2|x-x 15 Gnd
 Seed     03 x->|P0.2 P2.1|x-x 14 Gnd
 Lock/Key 04 x->|P0.3 P2.0|x-x 13 Gnd
 N/C      05 x- |Xout P1.3|<-x 12 Gnd/Reset speed B
 Clk in   06  ->|Xin  P1.2|<-x 11 Gnd/Reset speed A
 Reset    07  ->|Rset P1.1|x-> 10 Slave CIC reset
 Gnd      08 ---|Gnd  P1.0|x-> 09 /Host reset
                 ---------

TODO: add a connection diagram

The CPU

The CIC chip is a 4bit CPU. Well, more accurately an MCU as it contains its own ROM, RAM and I/O ports. I have searched extensively online and found interesting similarities between the instruction set proposed by Segher and a Rockwell PPS-4 CPU.

that original cic chips is the Sharp SM590 and SM595 microcomputers.

Programmer’s Model

8 7 6 5 4 3 2 1 0
C A
X
BH BL
PC
Stack[0]
Stack[1]
Stack[2]
Stack[3]
  • A – 4 bit accumulator
  • C – carry flag
  • X – 4 bit general purpose register
  • BL – lower 4 bits of RAM pointer
  • BH – upper 2 bits of RAM pointer
  • PC – program counter
  • Stack[0..3] – 4 level hardware stack for module calls

Program Counter

The Program Counter in the CIC cpu is quite peculiar. It is 10 bits wide and “increments” by shifting to the right and setting bit 6 if bit 1 and bit 0 are equal. The Program Counter never increments passed a 128 byte boundary; only a transfer module instruction can cause a jump passed a 128 byte boundary.

The behaviour of the Program Counter can be modeled as follows:

signal pc :  std_logic_vector(9 downto 0);

if (rising_edge(inc_pc)) then
    pc_s(5 downto 0) <= pc(6 downto 1);
    if pc(1) = pc(0) then
        pc(6) <= '1';
    else
        pc(6) <= '0';
    end if;
end if;

Of interesting note, the 2 byte Transfer Module opcodes, are not stored sequentially in ROM. Rather, they follow the same increment pattern as the Program Counter described above. Therefore, if we consider the 2 byte Transfer Module call found at address 0x17.

017: 7d 00   tml 200

The first byte, 0x7D, is stored at address 0x17. The second byte, 0x00, is stored at address 0x4B.

Instruction Set

Opcode Mnemonic Description Operation Notes
0x00 + N adi N add immediate skip if overflow A = A + N 1
0x10 + N skai N skip acc immediate if A = N skip 1
0x20 + N lbli N load B low immediate BL = N
0x30 + N ldi N load accumulator immediate A = N
40 l load A with *B A = *B
41 x exchange A and X A = X, X = A
42 xi exchange A and *B, increment BL, skip if overflow A = *B, *B = A, BL++ 1
43 xd exchange A and *B, decrement BL, skip if underflow A = *B, *B = A, BL– 1
44 nega negate accumulator A = -A
46 out output A to port number BL P[BL] = A
47 out0 output 0 to port number BL P[BL] = 0
48 sc set carry C = 1
49 rc reset carry C = 0
4A s store A to *B *B = A
4C rit return, pop PC from stack PC = Stack, Stack–
  1. Skipping the next instruction still uses the cycle time of the skipped instruction

Analyzing The Software

Segher has provided a commented disassembly of the CIC software. From this, I have counted the cycles to critical sections and determined the algorithms behaviour in order to port it to the PIC12F629 (work in progress).

Modules

The CPU makes calls to subroutines using an opcode called Transfer Module, therefore I will refer to subroutines as “modules” for consistency.

Module 0x103 – skip next instruction if lock

  • 5 cycles when key
  • BL = 0

This module tests the P0.3 pin to see if the host is a lock or a key. Since I am only interested in key mode, I can reduce module 0x103 to a 5 cycle burn which sets BL to 0 – never skipping the following instruction.

103: 20 lbli 0
141: 55 in
120: 67 ska 3
150: 8f t 10f
168: 4d ritsk
174: 74 lbmi 0
17a: 7c 83 tml 103
11e: 75 lbmi 1
10f: 4c rit

In key mode, the execution order is: 0x103, 0x141, 0x120, 0x150, 0x10f

Module 0x174 – B = other side

  • 10 cycles
  • BH = 1, BL = 0

This module is actually closely tied to module 0x103 above. The code sets BH to 1, then uses call module 0x103 (skip next instruction if lock) to skip over over 0x11E. In key mode, module 0x103 never skips, therefore we come back from module 0x103 and don’t skip the instruction at 0x11E (lbmi 1). Since I am only interested in key mode, I can reduce module 0x174 to an 10 cycle burn which sets BH to 1 and BL to 0.

103: 20 lbli 0
141: 55 in
120: 67 ska 3
150: 8f t 10f
168: 4d ritsk
174: 74 lbmi 0
17a: 7c 83 tml 103
11e: 75 lbmi 1
10f: 4c rit

In key mode, the execution order is: 0x174, 0x17a, 0x103, 0x141, 0x120, 0x150, 0x10f, 0x11e, 0x10f

Module 0x377 – Input Stream Bit

  • 10 cycles
  • Input sampled during 7th cycle

This module reads the input stream and stores it to the accumulator. It also sets BL = 0 and its entry and BL = 1 at exit for unknown reasons. The IN instruction at cycle 7 is the time where the input is read.

377: 20 lbli 0
37b: 00 nop
37d: 00 nop
33e: 00 nop
31f: 00 nop
34f: 00 nop
367: 55 in
373: 00 nop
379: 21 lbli 1
33c: 4c rit

The execution order is linear for this module.

Module 0x12f – Run Host

  • 16 cycles when key
  • BL = 1
  • Out = 0

This module sets all outputs to 0 (inactive) and loads BL with 1.

12f: 7c 83 tml 103
16b: e1 t 161
175: 31 ldi 1
13a: 21 lbli 1
11d: 00 nop
10e: 00 nop
107: 00 nop
143: dd t 15d 
161: 30 ldi 0
130: 21 lbli 1
158: 46 out
16c: 00 nop
176: 00 nop
13b: 00 nop
15d: 46 out
12e: 4c rit

The execution order of this module is: 0x12f (7 cycles), 0x16b, 0x161, 0x130, 0x158, 0x16c, 0x176, 0x13b, 0x15d, 0x12e

René

Electronics engineer and retrogaming fanatic!

2 thoughts on “NES CIC Lockout Chip

  • 2018-09-17 at 03:53
    Permalink

    Is the pic12f629 implementation mature enough to be used in new cartridge designs?

    I’ve been unable to get it working on my homemade board so far I compiled it with MPLABX and programmed the PIC using a GQ4-x4 without any issues. The board works fine in a top loader I suspect it may just be that my homemade board is too thin (0.8mm) to work in a front loader.

    Before I spend money getting boards of the proper thickness with hard gold plating etc, I’d appreciate it if you could confirm for me that it does work.

    Thanks.

    • 2018-10-01 at 06:47
      Permalink

      No this project is not yet completed.

Comments are closed.