Reading a CIC

D - through hole mounted

F - surface mounted (SuperFX, OBC1, maybe others)

411 - NTSC

413 - PAL

A / B - revision

Known CICs

  • D411 (NTSC carts)
  • D411A (NTSC carts)
  • D411B (NTSC carts)
  • D413 (PAL carts)
  • D413A (PAL carts)
  • D413B (PAL carts)
  • F411 (NTSC Console)
  • F411A (NTSC carts with SuperFX, OBC1, maybe others)
  • F411B (NTSC carts with SPC7110, maybe others)
  • F413A (PAL carts with SuperFX, OBC1, maybe others)

CIC Emulation / Simulation

Seeds with _ being the "stream select" bits from the lock in order 3-0-1-2 as usual:

D411
KEY: b14f4b57fd61e98 
LCK: _9a185f11e10dec 

D413
KEY: b14f4b57fd61e98 
LCK: _6a185f11e10dec

A quick hack in C that generates a D411's input and output streams:

#include <stdio.h>

void printseed(unsigned char* data) {
	int i;
	for(i=1;i<16;i++) {
		printf("%x ", data[i]);
	}
	printf("\n");
}

void printstream(unsigned char* data, int restart) {
	int i;
	for(i=restart;i<16;i++) {
		printf("%d ", data[i]&1);
	}
	printf("\n");
}

void mangle(unsigned char* data) {
	unsigned char a,x,temp,i,offset,carry=0;
	a=data[0xf];
	do {
		x=a;
		offset=1;
		carry=1;
		a+=data[offset]+carry;
		data[offset]=a&0xf;
		a=data[offset++];
		a+=data[offset]+carry;
		a=(~a)&0xf;
		temp=a; a=data[offset]; data[offset++]=temp&0xf;
		a+=data[offset]+carry;
		if(a<0x10) {
			temp=a; a=data[offset]; data[offset++]=temp&0xf;
		}
		a+=data[offset];
		data[offset]=a&0xf;
		a=data[offset++];
		carry=0;
		a+=data[offset]+carry;
		temp=a; a=data[offset]; data[offset++]=temp&0xf;
		a+=8;
		if(a<0x10) {
			a+=data[offset]+carry;
		}
		temp=a; a=data[offset]; data[offset++]=temp&0xf;
	
		while(offset<0x10) {
			a++;
			a+=data[offset]+carry;
			data[offset]=a&0xf;
			a=data[offset++];
		}
		offset &= 0xf;
		a=x;
		a+=0xf;
		if(a>0x0f) {
                        a &= 0xf;
                        carry=1;
                } else carry=0;
	} while(carry);
}

int main(void) {
	unsigned char restart=1;
	unsigned char keyseed_data[16]= {0x0, // dummy
			   0xb,0x1,0x4,0xf,
			   0x4,0xb,0x5,0x7,
			   0xf,0xd,0x6,0x1,
			   0xe,0x9,0x8};
	unsigned char lockseed_data[16]={0x0, // dummy
			   0x0,0x9,0xa,0x1,
			   0x8,0x5,0xf,0x1,
			   0x1,0xe,0x1,0x0,
			   0xd,0xe,0xc};

	unsigned char* keyseed=keyseed_data;
	unsigned char* lockseed=lockseed_data;
	printseed(keyseed);
	printseed(lockseed);
	printf("\n");

	while(1) {
		printf("\n");
		printstream(keyseed, restart);
		printstream(lockseed, restart);
		mangle(keyseed);
		mangle(keyseed);
		mangle(keyseed);
		mangle(lockseed);
		mangle(lockseed);
		mangle(lockseed);

	//	printseed(keyseed);
	//	printseed(lockseed);
		restart=lockseed_data[7];
		if(lockseed_data[7]&1) {
			keyseed=lockseed_data;
			lockseed=keyseed_data;
		} else {
			keyseed=keyseed_data;
			lockseed=lockseed_data;
		}
		if(!restart)restart=1;
	//	printf("send %d-15\n", restart);
	}
	return 0;
}