#include #include #include #include #ifdef _WIN32 #include #include #include typedef unsigned char uint8_t; typedef unsigned short uint16_t; typedef unsigned int uint32_t; #define mkdir(a, b) _mkdir(a) #define chdir _chdir #else #include #include #include #endif #define be16(x) ((((x)>>8)&0xFF)|((((x)<<8))&0xFF00)) #define be32(x) (((x)<<24)|(((x)>>8)&0xFF00)|(((x)<<8)&0xFF0000)|((x)>>24)) #define mem_free(x) {if (x != NULL){free(x);x=NULL;}} //convert hexstring to len bytes of data //returns 0 on success, -1 on error //data is a buffer of at least len bytes //hexstring is upper or lower case hexadecimal, NOT prepended with "0x" int hex2data(unsigned char *data, const unsigned char *hexstring, unsigned int len) { unsigned const char *pos = hexstring; char *endptr; size_t count = 0; if ((hexstring[0] == '\0') || (strlen(hexstring) % 2)) { //hexstring contains no data //or hexstring has an odd length return -1; } for(count = 0; count < len; count++) { char buf[5] = {'0', 'x', pos[0], pos[1], 0}; data[count] = strtol(buf, &endptr, 0); pos += 2 * sizeof(char); if (endptr[0] != '\0') { //non-hexadecimal character encountered return -1; } } return 0; } int main(int argc, char **argv) { printf("My Pokemon Ranch ID changer v0.2 by suloku\n"); printf("------------------------------------------\n"); printf("\tBuilt: " __TIME__ " " __DATE__ "\n"); printf("\tCopyright 2014 suloku>\n" "\tLicensed under the terms of the GNU GPL, version 2\n" "\thttp://www.gnu.org/licenses/old-licenses/gpl-2.0.txt\n\n\n"); FILE *file, *tnrfile; char pokemon[136]; unsigned long fileLen; char * buffer; FILE *pokefile; int pokecount = 1; uint8_t poke_type;// 01 trainer, 04 hayley, 05 traded uint16_t unknown1; uint8_t tradeable;// 02 is tradeable, normal 00 uint16_t tid; uint16_t sid; uint32_t name1; uint32_t name2; uint32_t name3; uint32_t name4; uint32_t unknown2; //unsigned char newtrainer[20]= {0xF5, 0xB8, 0x75, 0xD7, 0x3D, 0x01, 0x59, 0x01, 0x50, 0x01, 0x53, 0x01, 0x4f, 0x01, 0x59, 0x01, 0xff, 0xff, 0x00, 0x00}; unsigned char finalTID[2]; unsigned char finalSID[2]; unsigned char finalname[16]; //Open file file = fopen("savedata.bin", "rb"); if (!file) { printf("Unable to open savedata.bin\n\tPress enter to exit."); getchar(); return 0; } pokefile = fopen("savedata_new.bin", "wb"); if (!file) { printf("Unable to open savedata_new.bin\n\tPress enter to exit."); getchar(); return 0; } //Get file length fseek(file, 0, SEEK_END); fileLen=ftell(file); fseek(file, 0, SEEK_SET); // allocate memory to contain the whole file: buffer = (char*) malloc (sizeof(char)*fileLen); if (buffer == NULL) {printf ("Memory error\nPress enter to exit."); getchar(); return -1;} fseek(file, 0x22AC, SEEK_SET); uint32_t miientries; fread(&miientries, 4, 1, file); //printf ("Miientries %x\n", be32(miientries)); printf ("There are %4d Miis registered.\n", be32(miientries)); fseek(file, 0x22AC+(40*be32(miientries))+4+4, SEEK_SET); uint32_t miilinkentries; fread(&miilinkentries, 4, 1, file); //printf ("Miientries %x\n", be32(miilinkentries)); printf ("There are %4d trainers with stored pokemon.\n", be32(miilinkentries)); fseek(file, 0x22AC+(40*be32(miientries))+4+4+(44*be32(miilinkentries))+4+4, SEEK_SET); uint32_t pokemonentries; fread(&pokemonentries, 4, 1, file); //printf ("Miientries %x\n", be32(pokemonentries)); printf ("There are %4d pokemon stored (includes Hayley's pokemon).\n\n", be32(pokemonentries)); //Open .tnr file if specified tnrfile = fopen(argv[1], "rb"); if (!tnrfile) { printf("\nUnable to open %s trainer file. Press enter to manually input the data.\n", argv[1]); getchar(); printf ("\nPlease, enter the TID, SID and Name in HEX values (case insensitive), here's an example:\n"); printf ("\tTID: 47349 --> HEX: F5B8\n"); printf ("\tSID: 55157 --> HEX: 75D7\n"); printf ("\tName: Suloku --> HEX: 3D015901500153014F015901FFFF0000\n\n"); printf("Enter TID:\n"); char newTID[4]; gets(newTID); if (strlen (newTID) != 4){ printf("The input is too long/short. Exiting..."); getchar(); return 0; } if (hex2data(finalTID, newTID, 2) != 0){ printf("Wrong input. Exiting..."); getchar(); return 0; } printf("Enter SID:\n"); char newSID[4]; gets(newSID); if (strlen (newSID) != 4){ printf("The input is too long/short. Exiting..."); getchar(); return 0; } if (hex2data(finalSID, newSID, 2) != 0){ printf("Wrong input. Exiting..."); getchar(); return 0; } printf("Enter Name:\n"); char newNAME[32]; gets(newNAME); if (strlen (newNAME) != 32){ printf("The input is too long/short. Exiting..."); getchar(); return 0; } if (hex2data(finalname, newNAME, 16) != 0){ printf("Wrong input. Exiting..."); getchar(); return 0; } }else{ fread(finalTID, 2, 1, tnrfile); fread(finalSID, 2, 1, tnrfile); fread(finalname, 16, 1, tnrfile); } fclose(tnrfile); printf ("\tNew trainer information:\n"); printf ("\t\tTID HEX: %02X%02X\n", finalTID[0], finalTID[1]); printf ("\t\tSID HEX: %02X%02X\n", finalSID[0], finalSID[1]); printf ("\t\tName HEX: "); int j= 0; for (j=0;j<16;j++){ printf("%02X",finalname[j]); } //write this part of the file //Actually, the checksum at the header should be updated after editing the savegame file, //it seems to be at the header of the file, but I don't know how to do it. fseek(file, 0, SEEK_SET); fread(buffer, (0x22AC+(40*be32(miientries))+4+4+(44*be32(miilinkentries))+4+4+4), 1, file); //show current trainer in ranch int s; for(s=0;s