map: RAM:0x01~0x0f Seed 1 (own key seed)? RAM:0x10 send/receive buffer? RAM:0x11 Stream ID received from LOCK RAM:0x12~0x1f Seed 2 (Stream ID part of lock seed)? main: goto initstream; mainloop: a=0x1; mainloop2: x=a; for(x=a; x<16; x++) { main_inner1: bm=0x0; call 34b(0x00+x) // prepare next stream bit (send) bm=0x1; call 34b(0x10+x) // prepare next stream bit (recv) call 131 // bm=1; bl=0; a=P0 a=P0; if(P0.0) die; // WTF? P0.0 is an output! if(P0.1) die; a=0x0; a<->RAM[0x10]; // load A with next output stream bit (nibble) P0=a; // LSB -> Key output nop; // wait a=P0; // read from lock P0=0; // clear output port RAM[0x10]=a; // store next input stream bit in RAM bl=3; a=P3 // P3.0, which is usually UNCONNECTED, // somehow determines how to deal with // the input stream. This is SNES CIC specific. // NOTE: For commonly used key operation / pin mapping we must assume // that P3.0 is HIGH (1). (otherwise the key would die immediately) bl=0 if(P3.0){ if(RAM[0x10].1) { // input stream bit set? call 159 // bm=0; bl=0; a=P0 // switch "bank" if(RAM[0x00].0) { // matches calculated bit? goto 13d // then go on } else goto 157 // DIE // else gtfo } else goto input_stream_bit_clear // input stream bit clear, check } else goto 175 input_stream_bit_clear: // input stream bit cleared call 159 // bm=0; bl=0; a=P0 // switch "bank" if(RAM[0x00].0) { // calculated bit doesn't match? goto 157 // DIE // then die } else goto 17a // nop; goto 13d // else go on 175: if(RAM[0x10].0) { // this is essentially the same call 159 // bm=0; bl=0; a=P0 // as above but if(RAM[0x00].1) { // input stream bit is set in goto 13d; // RAM[0x10].0 instead of .1 and } else goto 157 // DIE // calculated from RAM[0x00].1 } else { // instead of .0, if P3.0 is 0. call 159 // bm=0; bl=0; a=P0 if(RAM[0x00].1) { goto 157 // DIE } else goto 17a // nop; goto 13d } 13d: // continue a=x; a++; // loop to next of 15 stream if(!overflow) { // bits, afterwards: x=a; goto main_inner1; } } // for x=1 to 15 (x=0) // call 04a // set Resets (dummy for key mode) // output reset levels call 370 // "MANGLE BOTH" // calculate new seeds call 370 // "MANGLE BOTH" // for both sides call 370 // "MANGLE BOTH" // (lock+key) to exchange // this is "SNES security": MANGLE is called THREE TIMES! // as opposed to only once on the NES CICs. a=RAM[0x13]; RAM[0x13]=RAM[0x17]; // set P3.0 to LSB of RAM[0x13] P3 = (P3 & 0xe) | (RAM[0x13] & 0x1); if(a.0==1) { goto mainloop (seed offset=0x1) } else goto mainloop2 (seed offset=a) 04a: // "RUN HOST" call 37a // "skip if lock" a=0x0; P1=a; nop nop nop P1=a; return mangle_both: call mangle(bm=0); goto mangle(bm=1); mangle: bl=0xf; a=RAM[bm:0xf]; x=a; carry=1; bl=0x1; a+=RAM[bm:0x1]+1; RAM[bm:0x1]=a; ==> RAM[bm:0x1]+=RAM[bm:0xf]+1; a=RAM[bm:0x1]; bl++; a+=RAM[bm:0x2]+1; a=~a; RAM[bm:0x2]=a; bl++; a+=RAM[bm:0x3]+1; if(!overflow) { RAM[bm:0x3]=a; bl++; } a+=RAM[bm:0x4]; RAM[bm:0x4]=a; a=RAM[bm:0x4]; bl++; carry=0; a+=RAM[bm:0x5]+0; RAM[bm:0x5]=a; bl++; a+=8; a+=RAM[bm:0x6]+0; RAM[bm:0x6]=a; bl++; mangle_inner1: a++; nop a+=RAM[bm:0x7..0xf]+0; RAM[bm:0x7..0xf]=a; a=RAM[bm:0x7..0xf]; bl++; if(!overflow) goto mangle_inner1 a<->x; a+=0xf; if(!overflow) return; goto mangle 131: bm=0x0; call 37a (if(!lock)bm=1); return; 37a: 34b: input x='bl' // take a nibble out of the seed (indexed by bm:x) // and set [bm:0], i.e. RAM[0x00] or RAM[0x10] like this: // if(seednibble&1) { // result=0b0000; // } else { // if(P3.0) { // result=0b0101; // } else { // result=0b0010; // } // } bl=x; a=RAM[bm:x]; RAM[bm:0] = RAM[bm:x].0 ? 0x7 : 0x0; a=P3; // WTF is P3???? bl=0; if (P3.0==1) { RAM[bm:0] &= 0b1101; } else { RAM[bm:0] &= 0b1010; } return initstream: if(P0.3==0) { if(P0.3==0) { A=RAM[0x11]; RAM[0x11]=0xf input_stream_id_bit; if !(A.1) RAM[0x11]&=0b0111 input_stream_id_bit; if !(A.1) RAM[0x11]&=0b1110 input_stream_id_bit; if !(A.1) RAM[0x11]&=0b1101 input_stream_id_bit; if !(A.1) RAM[0x11]&=0b1011 nop RAM[0x01]=0xb; RAM[0x02]=0x1; RAM[0x03]=0x4; RAM[0x04]=0xf; RAM[0x05]=0x4; RAM[0x06]=0xb; // 0x6???? RAM[0x07]=0x5; RAM[0x08]=0x7; // 0x8???? RAM[0x09]=0xf; RAM[0x0a]=0xd; // 0xa???? RAM[0x0b]=0x6; RAM[0x0c]=0x1; // 0xc???? RAM[0x0d]=0xe; RAM[0x0e]=0x9; RAM[0x0f]=0x8; RAM[0x12]=0x9; RAM[0x13]=0xa; RAM[0x14]=0x1; RAM[0x15]=0x8; RAM[0x16]=0x5; RAM[0x17]=0xf; // 0x7???? RAM[0x18]=0x1; RAM[0x19]=0x1; // 0x9???? RAM[0x1a]=0xe; RAM[0x1b]=0x1; // 0xb???? RAM[0x1c]=0x0; RAM[0x1d]=0xd; RAM[0x1e]=0xe; RAM[0x1f]=0xc; mainloop; } } input_stream_id_bit: wait 6 cycles A=P0 ret