/* GCNcrypt - Gamecube AR Crypto Program * * Copyright notice for this file: * Copyright (C) 2003-2004 Parasyte * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program; if not, write to the Free Software * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ #include "decrypt.h" void unscramble1(u32 *addr, u32 *val) { //80010568 u32 tmp; *val = rotate_left(*val,4); tmp = ((*addr^*val)&0xF0F0F0F0); *addr ^= tmp; *val = rotate_right((*val^tmp),0x14); tmp = ((*addr^*val)&0xFFFF0000); *addr ^= tmp; *val = rotate_right((*val^tmp),0x12); tmp = ((*addr^*val)&0x33333333); *addr ^= tmp; *val = rotate_right((*val^tmp),6); tmp = ((*addr^*val)&0x00FF00FF); *addr ^= tmp; *val = rotate_left((*val^tmp),9); tmp = ((*addr^*val)&0xAAAAAAAA); *addr = rotate_left((*addr^tmp),1); *val ^= tmp; } void unscramble2(u32 *addr, u32 *val) { //800106A4 u32 tmp; *val = rotate_right(*val,1); tmp = ((*addr^*val)&0xAAAAAAAA); *val ^= tmp; *addr = rotate_right((*addr^tmp),9); tmp = ((*addr^*val)&0x00FF00FF); *val ^= tmp; *addr = rotate_left((*addr^tmp),6); tmp = ((*addr^*val)&0x33333333); *val ^= tmp; *addr = rotate_left((*addr^tmp),0x12); tmp = ((*addr^*val)&0xFFFF0000); *val ^= tmp; *addr = rotate_left((*addr^tmp),0x14); tmp = ((*addr^*val)&0xF0F0F0F0); *val ^= tmp; *addr = rotate_right((*addr^tmp),4); } void decryptcode(u32 *seeds, u32 *code) { //800108C4 u32 addr,val; u32 tmp,tmp2; int i=0; getcode(code,&addr,&val); unscramble1(&addr,&val); while (i < 32) { tmp = (rotate_right(val,4)^seeds[i++]); tmp2 = (val^seeds[i++]); addr ^= (table6[tmp&0x3F]^table4[(tmp>>8)&0x3F]^table2[(tmp>>16)&0x3F]^table0[(tmp>>24)&0x3F]^table7[tmp2&0x3F]^table5[(tmp2>>8)&0x3F]^table3[(tmp2>>16)&0x3F]^table1[(tmp2>>24)&0x3F]); tmp = (rotate_right(addr,4)^seeds[i++]); tmp2 = (addr^seeds[i++]); val ^= (table6[tmp&0x3F]^table4[(tmp>>8)&0x3F]^table2[(tmp>>16)&0x3F]^table0[(tmp>>24)&0x3F]^table7[tmp2&0x3F]^table5[(tmp2>>8)&0x3F]^table3[(tmp2>>16)&0x3F]^table1[(tmp2>>24)&0x3F]); } unscramble2(&addr,&val); setcode(code,val,addr); } u8 getbitstring(u32 *ctrl, u32 *out, u8 len) { //80010BE0 u32 *ptr=(u32*)(ctrl[0]+(ctrl[1]<<2)); *out = 0; while (len--) { if (ctrl[2] > 0x1F) { ctrl[2] = 0; ctrl[1]++; ptr = (u32*)(ctrl[0]+(ctrl[1]<<2)); } if (ctrl[1] >= ctrl[3]) return 0; *out = ((*out<<1) | ((*ptr >> (0x1F-ctrl[2])) & 1)); ctrl[2]++; } return 1; } u8 batchdecrypt(u32 *codes, u16 size) { //80010C90 u32 tmp,tmp2,*ptr=codes; u32 tmparray[4] = { 0 },tmparray2[8] = { 0 }; // not required // if (size & 1) return 0; // if (!size) return 0; tmp = (size >> 1); while (tmp--) { decryptcode(genseeds,ptr); ptr+=2; } tmparray[0] = (u32)codes; tmparray[1] = 0; tmparray[2] = 4; //skip crc tmparray[3] = size; getbitstring(tmparray,tmparray2+1,11); //game id getbitstring(tmparray,tmparray2+2,17); //code id getbitstring(tmparray,tmparray2+3,1); //master code getbitstring(tmparray,tmparray2+4,1); //unknown getbitstring(tmparray,tmparray2+5,2); //region //grab gameid and region from the last decrypted code gameid = tmparray2[1]; region = tmparray2[5]; tmp = codes[0]; codes[0] &= 0x0FFFFFFF; if ((tmp>>28) != verifycode(codes,size)) return 0; return 1; //unfinished }