sd2snes/cic/d411.pseudo
2010-03-10 13:49:02 +01:00

231 lines
5.5 KiB
Plaintext

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