Skip to content

Instantly share code, notes, and snippets.

@Bl4ckSh4rk
Created July 6, 2017 23:10
Show Gist options
  • Save Bl4ckSh4rk/07ba2fff21dc80040bf1f4639afe2ca4 to your computer and use it in GitHub Desktop.
Save Bl4ckSh4rk/07ba2fff21dc80040bf1f4639afe2ca4 to your computer and use it in GitHub Desktop.
Fixes checksums in Yu-Gi-Oh! 5D's World Championship 2011 (NDS) save files
// YGOWC11SaveFix - fixes checksums in Yu-Gi-Oh! 5D's World Championship 2011 (NDS) save files
// Copyright (C) 2014 BlackShark
//
// 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 3 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, see <http://www.gnu.org/licenses/>.
#include <stdio.h>
#include <stdlib.h>
#include "crc32.c"
int main(int argc, char** argv)
{
uint32_t RAW_SAV_SIZE = 0x10000;
uint32_t DESMUME_SAV_SIZE = 0x1007A;
uint32_t CHECKSUM_AREA_OFFSET[2] = { 0x8500, 0xB838 };
uint32_t CHECKSUM_AREA_SIZE = 0x3334;
uint32_t CHECKSUM_OFFSET[2] = { 0xB834, 0xEB6C };
char WCS2011_SIGNATURE[7] = { 0x77, 0x63, 0x73, 0x32, 0x30, 0x31, 0x31 }; // wcs2011
printf("YGOWC11SaveFix - fixes save files of Yu-Gi-Oh! 5D's WC 2011\n");
if(argc != 2)
{
printf("usage: YGOWC11SaveFix.exe SAVEFILE\n");
return 0;
}
FILE *fp = fopen(argv[1], "rb+");
if (!fp)
{
printf("File loading failed\n");
fclose(fp);
return 0;
}
fseek (fp, 0, SEEK_END);
uint32_t fSize = ftell(fp);
if(fSize != RAW_SAV_SIZE && fSize != DESMUME_SAV_SIZE)
{
printf("Invalid file size (%d (0x%X))\n", fSize, fSize);
fclose(fp);
return 0;
}
char *signature = (char *)malloc(7);
fseek (fp, 0, SEEK_SET);
fread(signature, 1, 7, fp);
int x;
for(x = 0; x < 7; x++)
{
if(WCS2011_SIGNATURE[x] != signature[x])
{
printf("This is not a valid save file of Yu-Gi-Oh! 5D'S World Championship 2011 (NDS)\n");
free(signature);
fclose(fp);
return 0;
}
}
free(signature);
char *checksumArea = (char *)malloc(CHECKSUM_AREA_SIZE);
char *checksum = (char *)malloc(4);
uint32_t tmp = 0;
for(x = 0; x < 2; x++)
{
fseek (fp, CHECKSUM_AREA_OFFSET[x], SEEK_SET);
fread(checksumArea, 1, CHECKSUM_AREA_SIZE, fp);
if(checksumArea[0] == 0x53)
{
tmp = crc32(0, checksumArea, CHECKSUM_AREA_SIZE);
fseek (fp, CHECKSUM_OFFSET[x], SEEK_SET);
fread(checksum, 1, 4, fp);
checksum[0] = (char)(tmp);
checksum[1] = (char)((tmp >> 8));
checksum[2] = (char)((tmp >> 16));
checksum[3] = (char)((tmp >> 24));
fseek (fp, CHECKSUM_OFFSET[x], SEEK_SET);
fwrite(checksum, 1, 4, fp);
}
}
free(checksumArea);
free(checksum);
fclose(fp);
printf("Checksum fixed!\n");
return 0;
}
@Bl4ckSh4rk
Copy link
Author

Note: There are checksums in the "header" area (0 - 0x84FF) as well which are not fixed by this tool. Those are used for DLC stuff.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment