Work towards importing data.bin wii save files (issue 1945)

so far only tested with NSMB save (which works)
!!backup any existing save before importing save for the same game!!

also adds VS files and folders to the ignore list

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4784 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
LPFaint99 2010-01-05 07:34:03 +00:00
parent 736d84f5d6
commit 8b736cf7c5
7 changed files with 419 additions and 43 deletions

View File

@ -1097,46 +1097,6 @@
RelativePath=".\src\GameListCtrl.h"
>
</File>
<File
RelativePath=".\src\MemoryCards\GCMemcard.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
WarnAsError="false"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
WarnAsError="false"
/>
</FileConfiguration>
<FileConfiguration
Name="DebugFast|Win32"
>
<Tool
Name="VCCLCompilerTool"
WarnAsError="false"
/>
</FileConfiguration>
<FileConfiguration
Name="Release_JITIL|Win32"
>
<Tool
Name="VCCLCompilerTool"
WarnAsError="false"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\src\MemoryCards\GCMemcard.h"
>
</File>
<File
RelativePath=".\src\Globals.cpp"
>
@ -1505,6 +1465,58 @@
>
</File>
</Filter>
<Filter
Name="Saves"
>
<File
RelativePath=".\src\MemoryCards\GCMemcard.cpp"
>
<FileConfiguration
Name="Release|Win32"
>
<Tool
Name="VCCLCompilerTool"
WarnAsError="false"
/>
</FileConfiguration>
<FileConfiguration
Name="Debug|Win32"
>
<Tool
Name="VCCLCompilerTool"
WarnAsError="false"
/>
</FileConfiguration>
<FileConfiguration
Name="DebugFast|Win32"
>
<Tool
Name="VCCLCompilerTool"
WarnAsError="false"
/>
</FileConfiguration>
<FileConfiguration
Name="Release_JITIL|Win32"
>
<Tool
Name="VCCLCompilerTool"
WarnAsError="false"
/>
</FileConfiguration>
</File>
<File
RelativePath=".\src\MemoryCards\GCMemcard.h"
>
</File>
<File
RelativePath=".\Src\MemoryCards\WiiSaveCrypted.cpp"
>
</File>
<File
RelativePath=".\Src\MemoryCards\WiiSaveCrypted.h"
>
</File>
</Filter>
</Filter>
<Filter
Name="Misc"

View File

@ -239,6 +239,7 @@ EVT_MENU(IDM_NETPLAY, CFrame::OnNetPlay)
EVT_MENU(IDM_BROWSE, CFrame::OnBrowse)
EVT_MENU(IDM_MEMCARD, CFrame::OnMemcard)
EVT_MENU(IDM_IMPORTSAVE, CFrame::OnImportSave)
EVT_MENU(IDM_CHEATS, CFrame::OnShow_CheatsWindow)
EVT_MENU(IDM_CHANGEDISC, CFrame::OnChangeDisc)
EVT_MENU(IDM_LOAD_WII_MENU, CFrame::OnLoadWiiMenu)

View File

@ -308,6 +308,7 @@ class CFrame : public wxFrame
void OnHostMessage(wxCommandEvent& event);
void OnMemcard(wxCommandEvent& event); // Misc
void OnImportSave(wxCommandEvent& event);
void OnOpenLuaWindow(wxCommandEvent& event);
void OnNetPlay(wxCommandEvent& event);

View File

@ -49,6 +49,7 @@ Core::GetWindowHandle().
#include "ConfigMain.h"
#include "PluginManager.h"
#include "MemcardManager.h"
#include "MemoryCards/WiiSaveCrypted.h"
#include "CheatsWindow.h"
#include "LuaWindow.h"
#include "AboutDolphin.h"
@ -187,7 +188,8 @@ void CFrame::CreateMenu()
// Tools menu
wxMenu* toolsMenu = new wxMenu;
toolsMenu->Append(IDM_LUA, _T("New &Lua Console"));
toolsMenu->Append(IDM_MEMCARD, _T("&Memcard Manager"));
toolsMenu->Append(IDM_MEMCARD, _T("&Memcard Manager (GC)"));
toolsMenu->Append(IDM_IMPORTSAVE, _T("Wii Save Import (experimental)"));
toolsMenu->Append(IDM_CHEATS, _T("Action &Replay Manager"));
#if defined(HAVE_SFML) && HAVE_SFML
@ -782,10 +784,30 @@ void CFrame::OnNetPlay(wxCommandEvent& WXUNUSED (event))
void CFrame::OnMemcard(wxCommandEvent& WXUNUSED (event))
{
m_bModalDialogOpen = true;
m_bModalDialogOpen = true;
CMemcardManager MemcardManager(this);
MemcardManager.ShowModal();
m_bModalDialogOpen = false;
m_bModalDialogOpen = false;
}
void CFrame::OnImportSave(wxCommandEvent& WXUNUSED (event))
{
wxString path = wxFileSelector(_T("Select the save file"),
wxEmptyString, wxEmptyString, wxEmptyString,
wxString::Format
(
_T("Wii save files|data.bin|All files (%s)|%s"),
wxFileSelectorDefaultWildcardStr,
wxFileSelectorDefaultWildcardStr
),
wxFD_OPEN | wxFD_PREVIEW | wxFD_FILE_MUST_EXIST,
this);
if (!path.IsEmpty())
{
CWiiSaveCrypted saveFile(path.ToUTF8().data());
saveFile.Extract();
}
}
void CFrame::OnOpenLuaWindow(wxCommandEvent& WXUNUSED (event))

View File

@ -219,6 +219,7 @@ enum
IDM_NOTIFYMAPLOADED,
IDM_OPENCONTAININGFOLDER,
IDM_OPENSAVEFOLDER,
IDM_IMPORTSAVE,
IDM_SETDEFAULTGCM,
IDM_DELETEGCM,
IDM_COMPRESSGCM,

View File

@ -0,0 +1,225 @@
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Based off of tachtig http://git.infradead.org/?p=users/segher/wii.git
#include "stdafx.h"
#include "WiiSaveCrypted.h"
#include "FileUtil.h"
u8 SD_IV[0x10] = {0x21, 0x67, 0x12, 0xE6, 0xAA, 0x1F, 0x68, 0x9F,
0x95, 0xC5, 0xA2, 0x23, 0x24, 0xDC, 0x6A, 0x98};
CWiiSaveCrypted::CWiiSaveCrypted(const char* FileName)
{
_filename = std::string(FileName);
const u8 SDKey[16] = {0xAB, 0x01, 0xB9, 0xD8, 0xE1, 0x62, 0x2B, 0x08,
0xAF, 0xBA, 0xD8, 0x4D, 0xBF, 0xC2, 0xA5, 0x5D};
AES_set_decrypt_key(SDKey, 128, &m_AES_KEY);
b_valid = true;
ReadHDR();
ReadBKHDR();
}
void CWiiSaveCrypted::ReadHDR()
{
saveFileP = fopen(_filename.c_str(), "rb");
if (!saveFileP)
{
PanicAlert("Cannot open %s", _filename.c_str());
b_valid = false;
return;
}
Data_Bin_HDR * tmpHDR = new Data_Bin_HDR;
if (fread(tmpHDR, HDR_SZ, 1, saveFileP) != 1)
{
PanicAlert("failed to read header");
b_valid = false;
return;
}
AES_cbc_encrypt((const u8*)tmpHDR, (u8*)&hdr, HDR_SZ, &m_AES_KEY, SD_IV, AES_DECRYPT);
delete tmpHDR;
_bannerSize = Common::swap32(hdr.BannerSize);
if ((_bannerSize < FULL_BNR_MIN) || (_bannerSize > FULL_BNR_MAX) ||
(((_bannerSize - BNR_SZ) % ICON_SZ) != 0))
{
PanicAlert("not a wii save or read failure for file header size %x", _bannerSize);
b_valid = false;
return;
}
_saveGameTitle = Common::swap64(hdr.SaveGameTitle);
fclose(saveFileP);
}
void CWiiSaveCrypted::ReadBKHDR()
{
if (!b_valid) return;
saveFileP = fopen(_filename.c_str(), "rb");
if (!saveFileP)
{
PanicAlert("Cannot open %s", _filename.c_str());
b_valid = false;
return;
}
fseek(saveFileP, HDR_SZ + FULL_BNR_MAX/*_bannerSize*/, SEEK_SET);
if (fread(&bkhdr, BK_SZ, 1, saveFileP) != 1)
{
PanicAlert("failed to read bk header");
b_valid = false;
return;
}
if (Common::swap64((u8*)&bkhdr) != 0x00000070426b0001ULL)
{
PanicAlert("Invalid Size or Magic word %016llx", bkhdr);
b_valid = false;
return;
}
if (_saveGameTitle != Common::swap64(bkhdr.SaveGameTitle))
WARN_LOG(CONSOLE, "encrypted title (%x) does not match unencrypted title (%x)", _saveGameTitle, Common::swap64(bkhdr.SaveGameTitle));
_numberOfFiles = Common::swap32(bkhdr.numberOfFiles);
_sizeOfFiles = Common::swap32(bkhdr.sizeOfFiles);
_totalSize = Common::swap32(bkhdr.totalSize);
fclose(saveFileP);
}
void CWiiSaveCrypted::Extract()
{
if (!b_valid) return;
saveFileP = fopen(_filename.c_str(), "rb");
if (!saveFileP)
{
PanicAlert("Cannot open %s", _filename.c_str());
b_valid = false;
return;
}
sprintf(dir, FULL_WII_USER_DIR "title/%08x/%08x/data/", (u32)(_saveGameTitle>>32), (u32)_saveGameTitle);
if (!PanicYesNo("Warning! it is advised to backup all files in the folder:\n%s\nDo you wish to continue?", dir))
return;
INFO_LOG(CONSOLE, "%s", dir);
File::CreateFullPath(dir);
fseek(saveFileP, HDR_SZ, SEEK_SET);
_encryptedData = new u8[_bannerSize];
_data = new u8[_bannerSize];
if (fread(_encryptedData, _bannerSize, 1, saveFileP) != 1)
{
PanicAlert("failed to read banner");
b_valid = false;
return;
}
AES_cbc_encrypt((const u8*)_encryptedData, (u8*)_data, _bannerSize, &m_AES_KEY, SD_IV, AES_DECRYPT);
delete []_encryptedData;
sprintf(path, "%sbanner.bin", dir);
// remove after code is more thoroughly tested
sprintf(tmpPath, "%s.bak", path);
File::Copy(path, tmpPath);
//
if (!File::Exists(path) || PanicYesNo("%s already exists, overwrite?", path))
{
INFO_LOG(CONSOLE, "creating file %s", path);
outFileP = fopen(path, "wb");
if (outFileP)
{
fwrite(_data, _bannerSize, 1, outFileP);
fclose(outFileP);
}
}
delete []_data;
int lastpos = HDR_SZ + FULL_BNR_MAX /*_bannerSize */+ BK_SZ;
FileHDR _tmpFileHDR;
for(u32 i = 0; i < _numberOfFiles; i++)
{
fseek(saveFileP, lastpos, SEEK_SET);
memset(&_tmpFileHDR, 0, FILE_HDR_SZ);
memset(IV, 0, 0x10);
u32 roundedsize;
fread(&_tmpFileHDR, FILE_HDR_SZ, 1, saveFileP);
lastpos += FILE_HDR_SZ;
if(Common::swap32(_tmpFileHDR.magic) != 0x03adf17e)
{
PanicAlert("Bad File Header");
break;
}
else
{
sprintf(path, "%s%s", dir, _tmpFileHDR.name);
if (_tmpFileHDR.type == 2)
{
PanicAlert("savegame with a dir, report me :p, %s", path);
// we should prolly write any future files to this new dir
// but tachtig doesnt do this...
File::CreateFullPath(path);
}
else
{
roundedsize = (Common::swap32(_tmpFileHDR.size));// + 63) & ~63; // rounding makes corrupted files for NSMBwii
lastpos += roundedsize;
_encryptedData = new u8[roundedsize];
_data = new u8[roundedsize];
fread(_encryptedData, roundedsize, 1, saveFileP);
memcpy(IV, _tmpFileHDR.IV, 0x10);
AES_cbc_encrypt((const unsigned char *)_encryptedData, _data, roundedsize, &m_AES_KEY, IV, AES_DECRYPT);
delete []_encryptedData;
// remove after code is more thoroughly tested
sprintf(tmpPath, "%s.bak", path);
File::Copy(path, tmpPath);
//
if (!File::Exists(path) || PanicYesNo("%s already exists, overwrite?", path))
{
INFO_LOG(CONSOLE, "creating file %s", path);
outFileP = fopen(path, "wb");
if (outFileP)
{
fwrite(_data, roundedsize, 1, outFileP);
fclose(outFileP);
}
}
delete []_data;
}
}
}
fclose(saveFileP);
}
CWiiSaveCrypted::~CWiiSaveCrypted()
{
}

View File

@ -0,0 +1,114 @@
// Copyright (C) 2003 Dolphin Project.
// 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, version 2.0.
// 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 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _WII_SAVE_CRYPTED
#define _WII_SAVE_CRYPTED
#include "AES/aes.h"
#include "StringUtil.h"
// --- this is used for encrypted Wii save files
class CWiiSaveCrypted
{
public:
CWiiSaveCrypted(const char* FileName);
~CWiiSaveCrypted();
void ReadHDR();
void ReadBKHDR();
void Extract();
private:
FILE *saveFileP,
*outFileP;
AES_KEY m_AES_KEY;
u8 IV[0x10],
*_encryptedData,
*_data;
char dir[1024],
path[1024],
tmpPath[1024];
u32 _bannerSize,
_numberOfFiles,
_sizeOfFiles,
_totalSize;
u64 _saveGameTitle;
std::string _filename;
bool b_valid;
enum
{
HDR_SZ = 0x20,
BK_SZ = 0x80,
FILE_HDR_SZ = 0x80,
ICON_SZ = 0x1200,
BNR_SZ = 0x60a0,
FULL_BNR_MIN = 0x72a0, // BNR_SZ + 1*ICON_SZ
FULL_BNR_MAX = 0xF0A0, // BNR_SZ + 8*ICON_SZ
};
#pragma pack(push,1)
struct Data_Bin_HDR // encrypted
{
u64 SaveGameTitle;
u32 BannerSize; // (0x72A0 or 0xF0A0, also seen 0xBAA0)
u8 Permissions;
u8 unk1; // maybe permissions is a be16
u8 Md5[0x10]; // md5 of plaintext header with md5 blanker applied
u16 unk2;
}hdr;
struct BK_Header // Not encrypted
{
u32 size; // 0x00000070
u16 magic; // 'Bk'
u16 magic2; // or version (0x0001)
u32 NGid;
u32 numberOfFiles;
u32 sizeOfFiles;
u32 unk1;
u32 unk2;
u32 totalSize;
u8 unk3[64];
u64 SaveGameTitle;
u64 MACaddress;
u8 padding[0x10];
}bkhdr;
struct FileHDR // encrypted
{
u32 magic; //0x03adf17e
u32 size;
u8 Permissions;
u8 attrib;
u8 type; // (1=file, 2=directory)
u8 name[0x45];
u8 IV[0x10];
u8 unk[0x20];
};
#pragma pack(pop)
};
#endif