/* 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 "gcncrypt.h" int total; char ucase(char buffer) { if ((buffer >= 'a') && (buffer <= 'z')) buffer -= 0x20; return buffer; } int alphatobin(u32 *dst, char alpha[][14], int size) { int i,j=0,k; int ret=0,org=(size+1); u32 bin[2]; u8 parity; while (size) { bin[0]=0; for (i = 0; i < 6; i++) { bin[0] |= (GETVAL(filter,alpha[j>>1][i]) << (((5-i)*5)+2)); } bin[0] |= (GETVAL(filter,alpha[j>>1][6]) >> 3); dst[j++] = bin[0]; bin[1]=0; for (i = 0; i < 6; i++) { bin[1] |= (GETVAL(filter,alpha[j>>1][i+6]) << (((5-i)*5)+4)); } bin[1] |= (GETVAL(filter,alpha[j>>1][12]) >> 1); dst[j++] = bin[1]; //verify parity bit k=0; parity=0; for (i = 0; i < 64; i++) { if (i == 32) k++; parity ^= (bin[k] >> (i-(k<<5))); } if ((parity&1) != (GETVAL(filter,alpha[(j-2)>>1][12])&1)) ret=(org-size); size--; } return ret; } void DecryptUpdateText(char *textout, char alpha[][14], u32 *codes, int num) { char str[128]; int i,ret; total++; if ((ret=alphatobin(codes,alpha,num))) { sprintf(str,"Code Decryption Error\nParity Check Failed\n\nCode #%d, Line %d",total,ret); MessageBox(hWindow, str, "ERROR", MB_ICONERROR | MB_OK); batchdecrypt(codes,num<<1); } else if (!batchdecrypt(codes,num<<1)) { sprintf(str,"Code Decryption Error\nCRC Check Failed\n\nCode #%d",total); MessageBox(hWindow, str, "ERROR", MB_ICONERROR | MB_OK); } for (i = 0; i < (num<<1); i+=2) { sprintf(str,"%08X %08X\r\n",codes[i],codes[i+1]); strcat(textout,str); } } void DecryptParseList() { u32 codes[1200]; char textin[TEXTSIZE],textout[TEXTSIZE]; char alpha[600][14],tmp[14]; int i,j=0,num=0,chr=0,crlf=0; int strbegin=0,strend=0; total=0; memset(alpha,0,600*14); memset(textout,0,TEXTSIZE); SetDlgItemText(hWindow,102,""); GetDlgItemText(hWindow,101,textin,TEXTSIZE); //this thing runs through the input text, trying to find potential codes //when found, it virtually replaces them with decrypted codes for (i = 0; i < strlen(textin); i++) { if ((chr == 4) || (chr == 8)) { if (textin[i] != '-') chr=0; else if (++i >= TEXTSIZE) break; } if (ISALPHA(filter,ucase(textin[i]))) tmp[chr++] = ucase(textin[i]); else if (textin[i] == '\n') crlf++; else chr=0; if (chr == 13) { if ((strend < strbegin) || (!num)) strend = (i-14); chr=0; crlf=0; strcpy(alpha[num++],tmp); } if ((num) && (crlf > 1)) { memcpy(textout+strlen(textout),textin+strbegin,strend-strbegin); strbegin=(i-1); j = strlen(textout); while ((textout[j] != '\n') && (j >= 0)) textout[j--] = '\0'; DecryptUpdateText(textout,alpha,codes,num); num=0; } } if (((strend == 0) && (!num)) || (strbegin > strend)) strend=i; memcpy(textout+strlen(textout),textin+strbegin,strend-strbegin); if (num) { j = strlen(textout); while ((textout[j] != '\n') && (j >= 0)) textout[j--] = '\0'; DecryptUpdateText(textout,alpha,codes,num); } SetDlgItemText(hWindow,102,textout); if (dogameid) { sprintf(tmp,"%03X",gameid); SetDlgItemText(hWindow,103,tmp); SendMessage(GetDlgItem(hWindow,501),CB_SETCURSEL,(WPARAM)region,(LPARAM)0); } } void bintoalpha(char *dst, u32 *src, int index) { int i,j=0,k; u8 parity=0; //convert hex directly to alpha-numeric equivelant for (i = 0; i < 6; i++) { if (i == 4) { dst[i] = '-'; j++; } dst[i+j] = filter[(src[index] >> (((5-i)*5)+2)) & 0x1F]; } dst[i+j] = filter[((src[index]<<3)|(src[index+1]>>29))&0x1F]; j+=6; for (i = 1; i < 6; i++) { if (i == 2) { dst[i+j] = '-'; j++; } dst[i+j] = filter[(src[index+1] >> (((5-i)*5)+4)) & 0x1F]; } j+=i; //set parity bit k=0; for (i = 0; i < 64; i++) { if (i == 32) k++; parity ^= (src[index+k] >> (i-(k<<5))); } dst[j] = filter[((src[index+1]<<1)&0x1E)|(parity&1)]; dst[j+1] = '\0'; } void EncryptUpdateText(char *textout, u32 *codes, int num) { char str[128]; int i; total++; if (!batchencrypt(codes,num)) { sprintf(str,"Code Encryption Error\nCode #%d",total); MessageBox(hWindow, str, "ERROR", MB_ICONERROR | MB_OK); } for (i = 0; i < num; i+=2) { bintoalpha(str,codes,i); strcat(textout,str); strcat(textout,"\r\n"); } } void EncryptParseList() { u8 mcode; u32 codes[1200]; char textin[TEXTSIZE],textout[TEXTSIZE]; char alpha[600][14],tmp[18]; int i,j=0,num=0,chr=0,crlf=0; int strbegin=0,strend=0; total=0; //init random number generator srand(GetTickCount()); //get Game ID if (dogameid) { GetDlgItemText(hWindow,103,tmp,4); sscanf(tmp,"%hx",&gameid); gameid&=0x07FF; } memset(alpha,0,600*14); memset(textout,0,TEXTSIZE); memset(tmp,0,18); SetDlgItemText(hWindow,102,""); GetDlgItemText(hWindow,101,textin,TEXTSIZE); //this thing runs through the input text, trying to find potential codes //when found, it virtually replaces them with encrypted codes for (i = 0; i < strlen(textin); i++) { if (chr == 8) { if (textin[i] != ' ') chr=0; else tmp[chr++] = ' '; } else if (ISHEX(hex,ucase(textin[i]))) tmp[chr++] = ucase(textin[i]); else if (textin[i] == '\n') crlf++; else chr=0; if (chr == 17) { if ((strend < strbegin) || (!num)) strend = (i-16); chr=0; crlf=0; sscanf(tmp,"%x %x",&codes[num],&codes[num+1]); num+=2; } if ((num) && (crlf > 1)) { memcpy(textout+strlen(textout),textin+strbegin,strend-strbegin); strbegin=(i-1); j = strlen(textout); while ((textout[j] != '\n') && (j >= 0)) textout[j--] = '\0'; if (dogameid) { mcode=0; for (j = 0; j < num; j+=2) if ((codes[j] >> 25) == 0x62) mcode=1; region = SendMessage(GetDlgItem(hWindow,501),CB_GETCURSEL,(WPARAM)0,(LPARAM)0); j=num; num+=2; while (j >= 0) codes[j+2] = codes[j--]; codes[0] = ((gameid << 17)|(rand()%0x20000)); codes[1] = (0x08000000|(mcode<<31)|(region<<28)); } EncryptUpdateText(textout,codes,num); num=0; } } if (((strend == 0) && (!num)) || (strbegin > strend)) strend=i; memcpy(textout+strlen(textout),textin+strbegin,strend-strbegin); if (num) { j = strlen(textout); while ((textout[j] != '\n') && (j >= 0)) textout[j--] = '\0'; if (dogameid) { mcode=0; for (j = 0; j < num; j+=2) if ((codes[j] >> 25) == 0x62) mcode=1; region = SendMessage(GetDlgItem(hWindow,501),CB_GETCURSEL,(WPARAM)0,(LPARAM)0); j=num; num+=2; while (j >= 0) codes[j+2] = codes[j--]; codes[0] = ((gameid << 17)|(rand()%0x20000)); codes[1] = (0x08000000|(mcode<<31)|(region<<28)); } EncryptUpdateText(textout,codes,num); } SetDlgItemText(hWindow,102,textout); } void gcncryptKill() { DeleteObject(hNewFont); DestroyWindow(hWindow); hWindow=NULL; } BOOL CALLBACK MainCallB(HWND hwndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam) { LOGFONT lf; switch(uMsg) { case WM_INITDIALOG: //the almighty buildseeds() function!! without this, the crypto routines are useless buildseeds(); //setup font hFont = (HFONT)SendMessage(hwndDlg, WM_GETFONT, 0, 0); GetObject(hFont, sizeof(LOGFONT), &lf); strcpy(lf.lfFaceName,"Courier"); hNewFont = CreateFontIndirect(&lf); SendDlgItemMessage(hwndDlg,101,WM_SETFONT,(WPARAM)hNewFont,FALSE); SendDlgItemMessage(hwndDlg,102,WM_SETFONT,(WPARAM)hNewFont,FALSE); SendDlgItemMessage(hwndDlg,103,WM_SETFONT,(WPARAM)hNewFont,FALSE); //set text limits SendDlgItemMessage(hwndDlg,101,EM_SETLIMITTEXT,(TEXTSIZE-1),0); SendDlgItemMessage(hwndDlg,103,EM_SETLIMITTEXT,3,0); //tick checkbox CheckDlgButton(hwndDlg,401,BST_CHECKED); //fill region list box SendMessage(GetDlgItem(hwndDlg,501),CB_ADDSTRING,(WPARAM)0,(LPARAM)("USA")); SendMessage(GetDlgItem(hwndDlg,501),CB_ADDSTRING,(WPARAM)0,(LPARAM)("PAL")); SendMessage(GetDlgItem(hwndDlg,501),CB_ADDSTRING,(WPARAM)0,(LPARAM)("Japan")); SendMessage(GetDlgItem(hwndDlg,501),CB_ADDSTRING,(WPARAM)0,(LPARAM)("Null")); SendMessage(GetDlgItem(hwndDlg,501),CB_SETCURSEL,(WPARAM)0,(LPARAM)0); break; case WM_CLOSE: case WM_QUIT: gcncryptKill(); break; case WM_COMMAND: switch(HIWORD(wParam)) { case BN_CLICKED: switch(LOWORD(wParam)) { case 201: //Decrypt DecryptParseList(); break; case 202: //Encrypt EncryptParseList(); break; case 301: //Close gcncryptKill(); break; case 302: //Clear (input) SetDlgItemText(hwndDlg,101,""); break; case 303: //Clear (output) SetDlgItemText(hwndDlg,102,""); break; case 401: //Game ID: dogameid^=1; SendDlgItemMessage(hwndDlg,103,EM_SETREADONLY,dogameid^1,0); EnableWindow(GetDlgItem(hwndDlg,501),dogameid); break; } break; } break; } return FALSE; } int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hprevinstance, LPSTR lpcmdline, int ncmdshow) { MSG msg; RECT wndRect,dskRect; int w,h; ghInstance = hInstance; hWindow = CreateDialog(ghInstance,"MAIN",NULL,MainCallB); if (!hWindow) { MessageBox(NULL, "Could not create main dialog", "ERROR", MB_ICONERROR | MB_OK); return 0; } //load and set dialog icons iWindow = LoadIcon(ghInstance,"ICON"); SendMessage(hWindow,WM_SETICON,ICON_BIG,(LPARAM)iWindow); SendMessage(hWindow,WM_SETICON,ICON_SMALL,(LPARAM)iWindow); //change title bar to include version number SetWindowText(hWindow, TITLEBAR); //center dialog on screen GetWindowRect(hWindow,&wndRect); GetWindowRect(GetDesktopWindow(),&dskRect); w = (wndRect.right-wndRect.left); h = (wndRect.bottom-wndRect.top); MoveWindow(hWindow,((dskRect.right/2)-(w/2)),((dskRect.bottom/2)-(h/2)),w,h,TRUE); //display dialog ShowWindow(hWindow,ncmdshow); UpdateWindow(hWindow); while (hWindow) { if (GetMessage(&msg,NULL,0,0)) { TranslateMessage(&msg); DispatchMessage(&msg); } } return msg.wParam; }