mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-01-10 08:09:26 +01:00
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:
parent
736d84f5d6
commit
8b736cf7c5
@ -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"
|
||||
|
@ -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)
|
||||
|
@ -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);
|
||||
|
@ -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))
|
||||
|
@ -219,6 +219,7 @@ enum
|
||||
IDM_NOTIFYMAPLOADED,
|
||||
IDM_OPENCONTAININGFOLDER,
|
||||
IDM_OPENSAVEFOLDER,
|
||||
IDM_IMPORTSAVE,
|
||||
IDM_SETDEFAULTGCM,
|
||||
IDM_DELETEGCM,
|
||||
IDM_COMPRESSGCM,
|
||||
|
225
Source/Core/DolphinWX/Src/MemoryCards/WiiSaveCrypted.cpp
Normal file
225
Source/Core/DolphinWX/Src/MemoryCards/WiiSaveCrypted.cpp
Normal 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()
|
||||
{
|
||||
}
|
||||
|
114
Source/Core/DolphinWX/Src/MemoryCards/WiiSaveCrypted.h
Normal file
114
Source/Core/DolphinWX/Src/MemoryCards/WiiSaveCrypted.h
Normal 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
|
Loading…
x
Reference in New Issue
Block a user