Merge branch 'master' of https://code.google.com/p/dolphin-emu into android-core-control

This commit is contained in:
Lioncash
2013-09-01 15:24:29 -04:00
113 changed files with 1818 additions and 751 deletions
+2
View File
@@ -82,6 +82,8 @@
<string name="opengl_es3">OpenGL ES 3</string>
<string name="video_backend">ビデオレンダラ</string>
<string name="video_backend_to_use">使用するビデオレンダラー</string>
<string name="show_fps">FPSを表示</string>
<string name="show_fps_descrip">エミュレーション速度の指標として、画面左上に毎秒レンダリングされた フレーム数を表示します。</string>
<string name="draw_onscreen_controls">画面上のコントロールを描画</string>
<string name="enhancements">画質向上の設定</string>
+2
View File
@@ -82,6 +82,8 @@
<string name="opengl_es3">OpenGL ES 3</string>
<string name="video_backend">Video Backend</string>
<string name="video_backend_to_use">Video backend to use</string>
<string name="show_fps">Show FPS</string>
<string name="show_fps_descrip">Show the number of frames rendered per second as a measure of emulation speed.</string>
<string name="draw_onscreen_controls">Draw on-screen controls</string>
<string name="enhancements">Enhancements</string>
+30 -25
View File
@@ -3,66 +3,66 @@
<!-- Video Settings -->
<!-- Video Enhancements -->
<PreferenceScreen android:title="@string/enhancements">
<ListPreference
android:entries="@array/internalResolutionEntries"
android:entryValues="@array/internalResolutionValues"
android:key="internalResolution"
android:summary="@string/internal_resolution_descrip"
android:title="@string/internal_resolution"/>
<ListPreference
android:entries="@array/anisotropicFilteringEntries"
android:entryValues="@array/anisotropicFilteringValues"
android:key="anisotropicFiltering"
android:summary="@string/anisotropic_filtering_descrip"
android:title="@string/anisotropic_filtering"/>
<CheckBoxPreference
android:defaultValue="true"
android:key="scaledEFBCopy"
android:summary="@string/scaled_efb_copy_descrip"
android:title="@string/scaled_efb_copy"/>
<CheckBoxPreference
android:defaultValue="false"
android:key="perPixelLighting"
android:summary="@string/per_pixel_lighting_descrip"
android:title="@string/per_pixel_lighting"/>
<CheckBoxPreference
android:defaultValue="false"
android:key="forceTextureFiltering"
android:summary="@string/force_texture_filtering_descrip"
android:title="@string/force_texture_filtering"/>
<CheckBoxPreference
android:defaultValue="false"
android:key="disableFog"
android:summary="@string/disable_fog_descrip"
android:title="@string/disable_fog"/>
</PreferenceScreen>
<!-- Video Hacks -->
<PreferenceScreen android:title="@string/hacks">
<PreferenceCategory android:title="@string/embedded_frame_buffer">
<CheckBoxPreference
android:defaultValue="false"
android:key="skipEFBAccess"
android:summary="@string/skip_efb_access_descrip"
android:title="@string/skip_efb_access"/>
<CheckBoxPreference
android:defaultValue="true"
android:key="ignoreFormatChanges"
android:summary="@string/ignore_format_changes_descrip"
android:title="@string/ignore_format_changes"/>
<ListPreference
android:defaultValue="Texture"
android:entries="@array/efbCopyMethodEntries"
@@ -70,9 +70,9 @@
android:key="efbCopyMethod"
android:summary="@string/efb_copy_method_descrip"
android:title="@string/efb_copy_method"/>
</PreferenceCategory>
<!-- Texture Cache -->
<PreferenceCategory android:title="@string/texture_cache">
<ListPreference
@@ -83,7 +83,7 @@
android:summary="@string/texture_cache_accuracy_descrip"
android:title="@string/texture_cache_accuracy"/>
</PreferenceCategory>
<!-- External Frame Buffer -->
<PreferenceCategory android:title="@string/external_frame_buffer">
<ListPreference
@@ -94,36 +94,41 @@
android:summary="@string/external_frame_buffer_descrip"
android:title="@string/external_frame_buffer"/>
</PreferenceCategory>
<!-- Other Hacks -->
<PreferenceCategory android:title="@string/other">
<CheckBoxPreference
android:defaultValue="false"
android:key="cacheDisplayLists"
android:summary="@string/cache_display_lists_descrip"
android:title="@string/cache_display_lists"/>
<CheckBoxPreference
android:defaultValue="false"
android:key="disableDestinationAlpha"
android:summary="@string/disable_destination_alpha_descrip"
android:title="@string/disable_destination_alpha"/>
<CheckBoxPreference
android:defaultValue="true"
android:key="fastDepthCalculation"
android:summary="@string/fast_depth_calculation_descrip"
android:title="@string/fast_depth_calculation"/>
</PreferenceCategory>
</PreferenceScreen>
<ListPreference
android:key="gpuPref"
android:summary="@string/video_backend_to_use"
android:title="@string/video_backend" />
android:key="gpuPref"
android:summary="@string/video_backend_to_use"
android:title="@string/video_backend" />
<CheckBoxPreference
android:key="showFPS"
android:summary="@string/show_fps_descrip"
android:title="@string/show_fps"/>
<CheckBoxPreference
android:defaultValue="true"
@@ -28,14 +28,12 @@ import org.dolphinemu.dolphinemu.settings.VideoSettingsFragment;
public final class AboutFragment extends Fragment
{
private static Activity m_activity;
private ListView mMainList;
private AboutFragmentAdapter adapter;
@Override
public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState)
{
View rootView = inflater.inflate(R.layout.gamelist_listview, container, false);
mMainList = (ListView) rootView.findViewById(R.id.gamelist);
ListView mMainList = (ListView) rootView.findViewById(R.id.gamelist);
String yes = getString(R.string.yes);
String no = getString(R.string.no);
@@ -44,7 +42,7 @@ public final class AboutFragment extends Fragment
Input.add(new AboutFragmentItem(getString(R.string.build_revision), NativeLibrary.GetVersionString()));
Input.add(new AboutFragmentItem(getString(R.string.supports_gles3), VideoSettingsFragment.SupportsGLES3() ? yes : no));
adapter = new AboutFragmentAdapter(m_activity, R.layout.about_layout, Input);
AboutFragmentAdapter adapter = new AboutFragmentAdapter(m_activity, R.layout.about_layout, Input);
mMainList.setAdapter(adapter);
return mMainList;
@@ -18,10 +18,8 @@ import java.io.*;
/**
* The main activity of this emulator.
*
* @param <MainActivity> Main activity.
*/
public final class DolphinEmulator<MainActivity> extends Activity
public final class DolphinEmulator extends Activity
{
private void CopyAsset(String asset, String output)
{
@@ -14,7 +14,6 @@ import android.graphics.Color;
import android.graphics.drawable.ColorDrawable;
import android.os.Bundle;
import android.util.DisplayMetrics;
import android.util.Log;
import android.view.InputDevice;
import android.view.KeyEvent;
import android.view.Menu;
@@ -112,7 +112,7 @@ public final class FolderBrowser extends Fragment
return mDrawerList;
}
private AdapterView.OnItemClickListener mMenuItemClickListener = new AdapterView.OnItemClickListener()
private final AdapterView.OnItemClickListener mMenuItemClickListener = new AdapterView.OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
@@ -143,7 +143,6 @@ public final class FolderBrowser extends Fragment
{
String Directories = NativeLibrary.GetConfig("Dolphin.ini", "General", "GCMPathes", "0");
int intDirectories = Integer.parseInt(Directories);
Directories = Integer.toString(intDirectories + 1);
// Check to see if a path set in the Dolphin config
// matches the one the user is trying to add. If it's
@@ -178,7 +178,7 @@ public final class GameListActivity extends Activity
}
}
private AdapterView.OnItemClickListener mMenuItemClickListener = new AdapterView.OnItemClickListener()
private final AdapterView.OnItemClickListener mMenuItemClickListener = new AdapterView.OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
@@ -120,7 +120,7 @@ public final class GameListFragment extends Fragment
return mMainList;
}
private AdapterView.OnItemClickListener mGameItemClickListener = new AdapterView.OnItemClickListener()
private final AdapterView.OnItemClickListener mGameItemClickListener = new AdapterView.OnItemClickListener()
{
public void onItemClick(AdapterView<?> parent, View view, int position, long id)
{
@@ -30,11 +30,10 @@ import org.dolphinemu.dolphinemu.R;
* within the input control mapping config.
*/
public final class InputConfigFragment extends PreferenceFragment
//implements PrefsActivity.OnGameConfigListener
{
private Activity m_activity;
private boolean firstEvent = true;
private static ArrayList<Float> m_values = new ArrayList<Float>();
private static final ArrayList<Float> m_values = new ArrayList<Float>();
/**
* Gets the descriptor for the given {@link InputDevice}.
@@ -37,7 +37,8 @@ public final class UserPreferences
editor.putString("cpuCorePref", getConfig("Dolphin.ini", "Core", "CPUCore", "3"));
editor.putBoolean("dualCorePref", getConfig("Dolphin.ini", "Core", "CPUThread", "False").equals("True"));
editor.putString("gpuPref", getConfig("Dolphin.ini", "Core", "GFXBackend ", "Software Renderer"));
editor.putString("gpuPref", getConfig("Dolphin.ini", "Core", "GFXBackend ", "Software Renderer"));
editor.putBoolean("showFPS", getConfig("gfx_opengl.ini", "Settings", "ShowFPS", "False").equals("True"));
editor.putBoolean("drawOnscreenControls", getConfig("Dolphin.ini", "Android", "ScreenControls", "True").equals("True"));
editor.putString("internalResolution", getConfig("gfx_opengl.ini", "Settings", "EFBScale", "2") );
@@ -120,6 +121,9 @@ public final class UserPreferences
// Current video backend being used. Falls back to software rendering upon error.
String currentVideoBackend = prefs.getString("gpuPref", "Software Rendering");
// Whether or not FPS will be displayed on-screen.
boolean showingFPS = prefs.getBoolean("showFPS", false);
// Whether or not to draw on-screen controls.
boolean drawingOnscreenControls = prefs.getBoolean("drawOnscreenControls", true);
@@ -172,6 +176,7 @@ public final class UserPreferences
// General Video Settings
NativeLibrary.SetConfig("Dolphin.ini", "Core", "GFXBackend", currentVideoBackend);
NativeLibrary.SetConfig("gfx_opengl.ini", "Settings", "ShowFPS", showingFPS ? "True" : "False");
NativeLibrary.SetConfig("Dolphin.ini", "Android", "ScreenControls", drawingOnscreenControls ? "True" : "False");
// Video Hack Settings
@@ -16,9 +16,13 @@ import javax.microedition.khronos.opengles.GL10;
import org.dolphinemu.dolphinemu.R;
import android.app.Activity;
import android.content.SharedPreferences;
import android.content.SharedPreferences.OnSharedPreferenceChangeListener;
import android.os.Bundle;
import android.preference.ListPreference;
import android.preference.PreferenceFragment;
import android.preference.PreferenceManager;
import android.preference.PreferenceScreen;
/**
* Responsible for handling the loading of the video preferences.
@@ -195,6 +199,58 @@ public final class VideoSettingsFragment extends PreferenceFragment
videoBackends.setEntries(R.array.videoBackendEntriesNoGLES3);
videoBackends.setEntryValues(R.array.videoBackendValuesNoGLES3);
}
//
// Disable all options if Software Rendering is used.
//
// Note that the numeric value in 'getPreference()'
// denotes the placement on the UI. So if more elements are
// added to the video settings, these may need to change.
//
final SharedPreferences sPrefs = PreferenceManager.getDefaultSharedPreferences(getActivity());
final PreferenceScreen mainScreen = getPreferenceScreen();
if (videoBackends.getValue().equals("Software Renderer"))
{
mainScreen.getPreference(0).setEnabled(false);
mainScreen.getPreference(1).setEnabled(false);
mainScreen.getPreference(3).setEnabled(false);
mainScreen.getPreference(4).setEnabled(false);
}
else if (videoBackends.getValue().equals("OGL"))
{
mainScreen.getPreference(0).setEnabled(true);
mainScreen.getPreference(1).setEnabled(true);
mainScreen.getPreference(3).setEnabled(true);
mainScreen.getPreference(4).setEnabled(true);
}
// Also set a listener, so that if someone changes the video backend, it will disable
// the video settings, upon the user choosing "Software Rendering".
sPrefs.registerOnSharedPreferenceChangeListener(new OnSharedPreferenceChangeListener()
{
@Override
public void onSharedPreferenceChanged(SharedPreferences preference, String key)
{
if (key.equals("gpuPref"))
{
if (preference.getString(key, "Software Renderer").equals("Software Renderer"))
{
mainScreen.getPreference(0).setEnabled(false);
mainScreen.getPreference(1).setEnabled(false);
mainScreen.getPreference(3).setEnabled(false);
mainScreen.getPreference(4).setEnabled(false);
}
else if (preference.getString(key, "Software Renderer").equals("OGL"))
{
mainScreen.getPreference(0).setEnabled(true);
mainScreen.getPreference(1).setEnabled(true);
mainScreen.getPreference(3).setEnabled(true);
mainScreen.getPreference(4).setEnabled(true);
}
}
}
});
}
@Override
+4 -1
View File
@@ -1154,7 +1154,10 @@ void ARMXEmitter::VMOV(ARMReg Dest, ARMReg Src)
else
{
// Move 64bit from Arm reg
_dbg_assert_msg_(DYNA_REC, false, "This VMOV doesn't support moving 64bit ARM to NEON");
ARMReg Src2 = (ARMReg)(Src + 1);
Dest = SubBase(Dest);
Write32(condition | (0xC4 << 20) | (Src2 << 16) | (Src << 12) \
| (0xB << 8) | ((Dest & 0x10) << 1) | (1 << 4) | (Dest & 0xF));
return;
}
}
+10 -2
View File
@@ -25,15 +25,23 @@ extern const char *netplay_dolphin_ver;
#define STACKALIGN
#if __cplusplus >= 201103 || defined(_MSC_VER) || defined(__GXX_EXPERIMENTAL_CXX0X__)
#define HAVE_CXX11_SYNTAX 1
#endif
#if HAVE_CXX11_SYNTAX
// An inheritable class to disallow the copy constructor and operator= functions
class NonCopyable
{
protected:
NonCopyable() {}
NonCopyable(const NonCopyable&&) {}
void operator=(const NonCopyable&&) {}
private:
NonCopyable(const NonCopyable&);
void operator=(const NonCopyable&);
NonCopyable(NonCopyable&);
NonCopyable& operator=(NonCopyable& other);
};
#endif
#include "Log.h"
#include "CommonTypes.h"
+1 -1
View File
@@ -853,7 +853,7 @@ IOFile::IOFile(IOFile&& other)
IOFile& IOFile::operator=(IOFile&& other)
{
IOFile((IOFile&&)other).Swap(*this);
Swap(other);
return *this;
}
+4 -5
View File
@@ -143,7 +143,7 @@ bool ReadFileToString(bool text_file, const char *filename, std::string &str);
// simple wrapper for cstdlib file functions to
// hopefully will make error checking easier
// and make forgetting an fclose() harder
class IOFile
class IOFile : public NonCopyable
{
public:
IOFile();
@@ -209,12 +209,11 @@ public:
// clear error state
void Clear() { m_good = true; std::clearerr(m_file); }
private:
IOFile(const IOFile&) /*= delete*/;
IOFile& operator=(const IOFile&) /*= delete*/;
std::FILE* m_file;
bool m_good;
private:
IOFile(IOFile&);
IOFile& operator=(IOFile& other);
};
} // namespace
@@ -9,7 +9,7 @@
#define __has_include(s) 0
#endif
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
// GCC 4.4 provides <condition_variable>
#include <condition_variable>
+1 -1
View File
@@ -9,7 +9,7 @@
#define __has_include(s) 0
#endif
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
// GCC 4.4 provides <mutex>
#include <mutex>
#elif __has_include(<mutex>) && !ANDROID
+1 -1
View File
@@ -9,7 +9,7 @@
#define __has_include(s) 0
#endif
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ && !ANDROID
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__
// GCC 4.4 provides <thread>
#ifndef _GLIBCXX_USE_SCHED_YIELD
#define _GLIBCXX_USE_SCHED_YIELD
+13 -3
View File
@@ -19,6 +19,8 @@
#include "VolumeCreator.h"
#include "CommonPaths.h"
#include <memory>
static u32 state_checksum(u32 *buf, int len)
{
u32 checksum = 0;
@@ -89,9 +91,17 @@ bool CBoot::Boot_WiiWAD(const char* _pFilename)
WII_IPC_HLE_Interface::SetDefaultContentFile(_pFilename);
CDolLoader DolLoader(pContent->m_pData, pContent->m_Size);
DolLoader.Load();
PC = DolLoader.GetEntryPoint() | 0x80000000;
std::unique_ptr<CDolLoader> pDolLoader;
if (pContent->m_pData)
{
pDolLoader.reset(new CDolLoader(pContent->m_pData, pContent->m_Size));
}
else
{
pDolLoader.reset(new CDolLoader(pContent->m_Filename.c_str()));
}
pDolLoader->Load();
PC = pDolLoader->GetEntryPoint() | 0x80000000;
// Pass the "#002 check"
// Apploader should write the IOS version and revision to 0x3140, and compare it
+1 -1
View File
@@ -450,7 +450,7 @@ void SConfig::LoadSettings()
#elif defined __APPLE__
ini.Get("DSP", "Backend", &sBackend, BACKEND_COREAUDIO);
#elif defined _WIN32
ini.Get("DSP", "Backend", &sBackend, BACKEND_DIRECTSOUND);
ini.Get("DSP", "Backend", &sBackend, BACKEND_XAUDIO2);
#elif defined ANDROID
ini.Get("DSP", "Backend", &sBackend, BACKEND_OPENSLES);
#else
@@ -14,7 +14,7 @@ CUCode_AX::CUCode_AX(DSPHLE* dsp_hle, u32 crc)
: IUCode(dsp_hle, crc)
, m_work_available(false)
, m_cmdlist_size(0)
, m_run_on_thread(SConfig::GetInstance().m_LocalCoreStartupParameter.bDSPThread)
, m_run_on_thread(false)
{
WARN_LOG(DSPHLE, "Instantiating CUCode_AX: crc=%08x", crc);
m_rMailHandler.PushMail(DSP_INIT);
@@ -22,6 +22,9 @@ CUCode_AX::CUCode_AX(DSPHLE* dsp_hle, u32 crc)
LoadResamplingCoefficients();
// DSP HLE on thread is always disabled because it causes audio
// issues/glitching (different timing characteristics). m_run_on_thread is
// always false.
if (m_run_on_thread)
m_axthread = std::thread(SpawnAXThread, this);
}
+2 -4
View File
@@ -262,9 +262,7 @@ void Init()
if (Movie::IsRecordingInput() || Movie::IsPlayingInput())
AddDevice(Movie::IsUsingPad(i) ? (Movie::IsUsingBongo(i) ? SIDEVICE_GC_TARUKONGA : SIDEVICE_GC_CONTROLLER) : SIDEVICE_NONE, i);
else if (NetPlay::IsNetPlayRunning())
AddDevice((SIDevices) g_NetPlaySettings.m_Controllers[i], i);
else
else if (!NetPlay::IsNetPlayRunning())
AddDevice(SConfig::GetInstance().m_SIDevice[i], i);
}
@@ -567,7 +565,7 @@ void AddDevice(ISIDevice* pDevice)
void AddDevice(const SIDevices _device, int _iDeviceNumber)
{
ISIDevice* pDevice = SIDevice_Create(_device, _iDeviceNumber);
ISIDevice *pDevice = SIDevice_Create(_device, _iDeviceNumber);
AddDevice(pDevice);
}
@@ -60,7 +60,7 @@ CWII_IPC_HLE_Device_es::CWII_IPC_HLE_Device_es(u32 _DeviceID, const std::string&
: IWII_IPC_HLE_Device(_DeviceID, _rDeviceName)
, m_pContentLoader(NULL)
, m_TitleID(-1)
, AccessIdentID(0x6000000)
, m_AccessIdentID(0x6000000)
{
}
@@ -91,7 +91,7 @@ void CWII_IPC_HLE_Device_es::LoadWAD(const std::string& _rContentFile)
m_ContentFile = _rContentFile;
}
bool CWII_IPC_HLE_Device_es::Open(u32 _CommandAddress, u32 _Mode)
void CWII_IPC_HLE_Device_es::OpenInternal()
{
m_pContentLoader = &DiscIO::CNANDContentManager::Access().GetNANDLoader(m_ContentFile);
@@ -119,6 +119,57 @@ bool CWII_IPC_HLE_Device_es::Open(u32 _CommandAddress, u32 _Mode)
}
INFO_LOG(WII_IPC_ES, "Set default title to %08x/%08x", (u32)(m_TitleID>>32), (u32)m_TitleID);
}
void CWII_IPC_HLE_Device_es::DoState(PointerWrap& p)
{
IWII_IPC_HLE_Device::DoState(p);
p.Do(m_ContentFile);
OpenInternal();
p.Do(m_AccessIdentID);
p.Do(m_TitleIDs);
u32 Count = m_ContentAccessMap.size();
p.Do(Count);
u32 CFD, Position;
u64 TitleID;
u16 Index;
if (p.GetMode() == PointerWrap::MODE_READ)
{
for (u32 i = 0; i < Count; i++)
{
p.Do(CFD);
p.Do(Position);
p.Do(TitleID);
p.Do(Index);
CFD = OpenTitleContent(CFD, TitleID, Index);
if (CFD != 0xffffffff)
{
m_ContentAccessMap[CFD].m_Position = Position;
}
}
}
else
{
for (auto itr = m_ContentAccessMap.begin(); itr != m_ContentAccessMap.end(); ++itr)
{
CFD = itr->first;
SContentAccess& Access = itr->second;
Position = Access.m_Position;
TitleID = Access.m_TitleID;
Index = Access.m_pContent->m_Index;
p.Do(CFD);
p.Do(Position);
p.Do(TitleID);
p.Do(Index);
}
}
}
bool CWII_IPC_HLE_Device_es::Open(u32 _CommandAddress, u32 _Mode)
{
OpenInternal();
Memory::Write_U32(GetDeviceID(), _CommandAddress+4);
if (m_Active)
@@ -131,11 +182,15 @@ bool CWII_IPC_HLE_Device_es::Close(u32 _CommandAddress, bool _bForce)
{
// Leave deletion of the INANDContentLoader objects to CNANDContentManager, don't do it here!
m_NANDContent.clear();
for (auto itr = m_ContentAccessMap.begin(); itr != m_ContentAccessMap.end(); ++itr)
{
delete itr->second.m_pFile;
}
m_ContentAccessMap.clear();
m_pContentLoader = NULL;
m_TitleIDs.clear();
m_TitleID = -1;
AccessIdentID = 0x6000000;
m_AccessIdentID = 0x6000000;
INFO_LOG(WII_IPC_ES, "ES: Close");
if (!_bForce)
@@ -144,6 +199,45 @@ bool CWII_IPC_HLE_Device_es::Close(u32 _CommandAddress, bool _bForce)
return true;
}
u32 CWII_IPC_HLE_Device_es::OpenTitleContent(u32 CFD, u64 TitleID, u16 Index)
{
const DiscIO::INANDContentLoader& Loader = AccessContentDevice(TitleID);
if (!Loader.IsValid())
{
WARN_LOG(WII_IPC_ES, "ES: loader not valid for %llx", TitleID);
return 0xffffffff;
}
const DiscIO::SNANDContent* pContent = Loader.GetContentByIndex(Index);
if (pContent == NULL)
{
return 0xffffffff; //TODO: what is the correct error value here?
}
SContentAccess Access;
Access.m_Position = 0;
Access.m_pContent = pContent;
Access.m_TitleID = TitleID;
if (!pContent->m_pData)
{
std::string Filename = pContent->m_Filename;
INFO_LOG(WII_IPC_ES, "ES: load %s", Filename.c_str());
Access.m_pFile = new File::IOFile(Filename, "rb");
if (!Access.m_pFile->IsGood())
{
WARN_LOG(WII_IPC_ES, "ES: couldn't load %s", Filename.c_str());
return 0xffffffff;
}
}
m_ContentAccessMap[CFD] = Access;
return CFD;
}
bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
{
SIOCtlVBuffer Buffer(_CommandAddress);
@@ -242,16 +336,11 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
u64 TitleID = Memory::Read_U64(Buffer.InBuffer[0].m_Address);
u32 Index = Memory::Read_U32(Buffer.InBuffer[2].m_Address);
u32 CFD = AccessIdentID++;
m_ContentAccessMap[CFD].m_Position = 0;
m_ContentAccessMap[CFD].m_pContent = AccessContentDevice(TitleID).GetContentByIndex(Index);
_dbg_assert_msg_(WII_IPC_ES, m_ContentAccessMap[CFD].m_pContent != NULL, "No Content for TitleID: %08x/%08x at Index %x", (u32)(TitleID>>32), (u32)TitleID, Index);
// Fix for DLC by itsnotmailmail
if (m_ContentAccessMap[CFD].m_pContent == NULL)
CFD = 0xffffffff; //TODO: what is the correct error value here?
u32 CFD = OpenTitleContent(m_AccessIdentID++, TitleID, Index);
Memory::Write_U32(CFD, _CommandAddress + 0x4);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENTITLECONTENT: TitleID: %08x/%08x Index %i -> got CFD %x", (u32)(TitleID>>32), (u32)TitleID, Index, CFD);
return true;
}
break;
@@ -260,19 +349,12 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
{
_dbg_assert_(WII_IPC_ES, Buffer.NumberInBuffer == 1);
_dbg_assert_(WII_IPC_ES, Buffer.NumberPayloadBuffer == 0);
u32 CFD = AccessIdentID++;
u32 Index = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
m_ContentAccessMap[CFD].m_Position = 0;
m_ContentAccessMap[CFD].m_pContent = AccessContentDevice(m_TitleID).GetContentByIndex(Index);
if (m_ContentAccessMap[CFD].m_pContent == NULL)
CFD = 0xffffffff; //TODO: what is the correct error value here?
u32 CFD = OpenTitleContent(m_AccessIdentID++, m_TitleID, Index);
Memory::Write_U32(CFD, _CommandAddress + 0x4);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_OPENCONTENT: Index %i -> got CFD %x", Index, CFD);
return true;
}
break;
@@ -286,12 +368,16 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
u32 Size = Buffer.PayloadBuffer[0].m_Size;
u32 Addr = Buffer.PayloadBuffer[0].m_Address;
_dbg_assert_(WII_IPC_ES, m_ContentAccessMap.find(CFD) != m_ContentAccessMap.end());
SContentAccess& rContent = m_ContentAccessMap[CFD];
auto itr = m_ContentAccessMap.find(CFD);
if (itr == m_ContentAccessMap.end())
{
Memory::Write_U32(-1, _CommandAddress + 0x4);
return true;
}
SContentAccess& rContent = itr->second;
_dbg_assert_(WII_IPC_ES, rContent.m_pContent->m_pData != NULL);
u8* pSrc = &rContent.m_pContent->m_pData[rContent.m_Position];
u8* pDest = Memory::GetPointer(Addr);
if (rContent.m_Position + Size > rContent.m_pContent->m_Size)
@@ -301,8 +387,26 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
if (Size > 0)
{
if (pDest) {
memcpy(pDest, pSrc, Size);
if (pDest)
{
if (rContent.m_pContent->m_pData)
{
u8* pSrc = &rContent.m_pContent->m_pData[rContent.m_Position];
memcpy(pDest, pSrc, Size);
}
else
{
auto& pFile = rContent.m_pFile;
if (!pFile->Seek(rContent.m_Position, SEEK_SET))
{
ERROR_LOG(WII_IPC_ES, "ES: couldn't seek!");
}
WARN_LOG(WII_IPC_ES, "2 %p", pFile->GetHandle());
if (!pFile->ReadBytes(pDest, Size))
{
ERROR_LOG(WII_IPC_ES, "ES: short read; returning uninitialized data!");
}
}
rContent.m_Position += Size;
} else {
PanicAlertT("IOCTL_ES_READCONTENT - bad destination");
@@ -323,11 +427,18 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
u32 CFD = Memory::Read_U32(Buffer.InBuffer[0].m_Address);
CContentAccessMap::iterator itr = m_ContentAccessMap.find(CFD);
m_ContentAccessMap.erase(itr);
INFO_LOG(WII_IPC_ES, "IOCTL_ES_CLOSECONTENT: CFD %x", CFD);
auto itr = m_ContentAccessMap.find(CFD);
if (itr == m_ContentAccessMap.end())
{
Memory::Write_U32(-1, _CommandAddress + 0x4);
return true;
}
delete itr->second.m_pFile;
m_ContentAccessMap.erase(itr);
Memory::Write_U32(0, _CommandAddress + 0x4);
return true;
}
@@ -342,8 +453,13 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
u32 Addr = Memory::Read_U32(Buffer.InBuffer[1].m_Address);
u32 Mode = Memory::Read_U32(Buffer.InBuffer[2].m_Address);
_dbg_assert_(WII_IPC_ES, m_ContentAccessMap.find(CFD) != m_ContentAccessMap.end());
SContentAccess& rContent = m_ContentAccessMap[CFD];
auto itr = m_ContentAccessMap.find(CFD);
if (itr == m_ContentAccessMap.end())
{
Memory::Write_U32(-1, _CommandAddress + 0x4);
return true;
}
SContentAccess& rContent = itr->second;
switch (Mode)
{
@@ -759,12 +875,19 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
if (pContent)
{
LoadWAD(Common::GetTitleContentPath(TitleID));
CDolLoader DolLoader(pContent->m_pData, pContent->m_Size);
DolLoader.Load(); // TODO: Check why sysmenu does not load the DOL correctly
PC = DolLoader.GetEntryPoint() | 0x80000000;
std::unique_ptr<CDolLoader> pDolLoader;
if (pContent->m_pData)
{
pDolLoader.reset(new CDolLoader(pContent->m_pData, pContent->m_Size));
}
else
{
pDolLoader.reset(new CDolLoader(pContent->m_Filename.c_str()));
}
pDolLoader->Load(); // TODO: Check why sysmenu does not load the DOL correctly
PC = pDolLoader->GetEntryPoint() | 0x80000000;
IOSv = ContentLoader.GetIosVersion();
bSuccess = true;
}
}
}
@@ -908,7 +1031,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress)
const DiscIO::INANDContentLoader& CWII_IPC_HLE_Device_es::AccessContentDevice(u64 _TitleID)
{
if (m_pContentLoader->IsValid() && m_pContentLoader->GetTitleID() == _TitleID)
return* m_pContentLoader;
return *m_pContentLoader;
CTitleToContentMap::iterator itr = m_NANDContent.find(_TitleID);
if (itr != m_NANDContent.end())
@@ -8,6 +8,7 @@
#include <map>
#include "WII_IPC_HLE_Device.h"
#include "NANDContentLoader.h"
#include <memory>
class CWII_IPC_HLE_Device_es : public IWII_IPC_HLE_Device
{
@@ -19,6 +20,10 @@ public:
void LoadWAD(const std::string& _rContentFile);
void OpenInternal();
virtual void DoState(PointerWrap& p);
virtual bool Open(u32 _CommandAddress, u32 _Mode);
virtual bool Close(u32 _CommandAddress, bool _bForce);
@@ -108,10 +113,13 @@ private:
ES_HASH_SIZE_WRONG = -2014, // HASH !=20
};
struct SContentAccess
struct SContentAccess
{
u32 m_Position;
u64 m_TitleID;
const DiscIO::SNANDContent* m_pContent;
// This is a (raw) pointer to work around a MSVC bug.
File::IOFile* m_pFile;
};
typedef std::map<u32, SContentAccess> CContentAccessMap;
@@ -124,13 +132,14 @@ private:
std::vector<u64> m_TitleIDs;
u64 m_TitleID;
u32 AccessIdentID;
u32 m_AccessIdentID;
static u8 *keyTable[11];
u64 GetCurrentTitleID() const;
const DiscIO::INANDContentLoader& AccessContentDevice(u64 _TitleID);
u32 OpenTitleContent(u32 CFD, u64 TitleID, u16 Index);
bool IsValid(u64 _TitleID) const;
@@ -709,14 +709,14 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 _CommandAddress)
}
case IOCTL_SO_LISTEN:
{
INFO_LOG(WII_IPC_NET, "IOCTL_SO_LISTEN "
"BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
BufferIn, BufferInSize, BufferOut, BufferOutSize);
u32 fd = Memory::Read_U32(BufferIn);
u32 BACKLOG = Memory::Read_U32(BufferIn + 0x04);
u32 ret = listen(fd, BACKLOG);
ReturnValue = WiiSockMan::getNetErrorCode(ret, "SO_LISTEN", false);
INFO_LOG(WII_IPC_NET, "IOCTL_SO_LISTEN = %d "
"BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
ReturnValue, BufferIn, BufferInSize, BufferOut, BufferOutSize);
break;
}
case IOCTL_SO_GETSOCKOPT:
@@ -755,6 +755,13 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 _CommandAddress)
s32 errorcode = Memory::Read_U32(BufferOut + 0x10);
INFO_LOG(WII_IPC_NET,"IOCTL_SO_GETSOCKOPT error code = %i", errorcode);
}
else if (optname == SO_ERROR)
{
s32 last_error = WiiSockMan::getInstance().getLastNetError();
Memory::Write_U32(sizeof(s32), BufferOut + 0xC);
Memory::Write_U32(last_error, BufferOut + 0x10);
}
break;
}
@@ -767,14 +774,16 @@ bool CWII_IPC_HLE_Device_net_ip_top::IOCtl(u32 _CommandAddress)
u8 optval[20];
Memory::ReadBigEData(optval, BufferIn + 0x10, optlen);
//TODO: bug booto about this, 0x2005 most likely timeout related, default value on wii is , 0x2001 is most likely tcpnodelay
if (level == 6 && (optname == 0x2005 || optname == 0x2001)){
return 0;
}
INFO_LOG(WII_IPC_NET, "IOCTL_SO_SETSOCKOPT(%08x, %08x, %08x, %08x) "
"BufferIn: (%08x, %i), BufferOut: (%08x, %i)"
"%02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx %02hhx",
fd, level, optname, optlen, BufferIn, BufferInSize, BufferOut, BufferOutSize, optval[0], optval[1], optval[2], optval[3], optval[4], optval[5], optval[6], optval[7], optval[8], optval[9], optval[10], optval[11], optval[12], optval[13], optval[14], optval[15], optval[16], optval[17], optval[18], optval[19]);
//TODO: bug booto about this, 0x2005 most likely timeout related, default value on wii is , 0x2001 is most likely tcpnodelay
if (level == 6 && (optname == 0x2005 || optname == 0x2001)){
ReturnValue = 0;
break;
}
// Do the level/optname translation
int nat_level = -1, nat_optname = -1;
+74 -58
View File
@@ -37,21 +37,9 @@ char* WiiSockMan::DecodeError(s32 ErrorCode)
#endif
}
s32 WiiSockMan::getNetErrorCode(s32 ret, std::string caller, bool isRW)
s32 translateErrorCode(s32 native_error, bool isRW)
{
#ifdef _WIN32
s32 errorCode = WSAGetLastError();
#else
s32 errorCode = errno;
#endif
if (ret >= 0)
return ret;
DEBUG_LOG(WII_IPC_NET, "%s failed with error %d: %s, ret= %d",
caller.c_str(), errorCode, DecodeError(errorCode), ret);
switch (errorCode)
switch (native_error)
{
case ERRORCODE(EMSGSIZE):
ERROR_LOG(WII_IPC_NET, "Find out why this happened, looks like PEEK failure?");
@@ -87,7 +75,29 @@ s32 WiiSockMan::getNetErrorCode(s32 ret, std::string caller, bool isRW)
default:
return -1;
}
}
s32 WiiSockMan::getNetErrorCode(s32 ret, std::string caller, bool isRW)
{
#ifdef _WIN32
s32 errorCode = WSAGetLastError();
#else
s32 errorCode = errno;
#endif
if (ret >= 0)
{
WiiSockMan::getInstance().setLastNetError(ret);
return ret;
}
INFO_LOG(WII_IPC_NET, "%s failed with error %d: %s, ret= %d",
caller.c_str(), errorCode, DecodeError(errorCode), ret);
s32 ReturnValue = translateErrorCode(errorCode, isRW);
WiiSockMan::getInstance().setLastNetError(ReturnValue);
return ReturnValue;
}
WiiSocket::~WiiSocket()
@@ -224,7 +234,7 @@ void WiiSocket::update(bool read, bool write, bool except)
WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferOut);
WiiSockMan::Convert(*wii_name, local_name);
socklen_t addrlen = wii_name->len;
socklen_t addrlen = sizeof(sockaddr_in);
int ret = (s32)accept(fd, (sockaddr*)&local_name, &addrlen);
ReturnValue = WiiSockMan::getNetErrorCode(ret, "SO_ACCEPT", false);
@@ -235,7 +245,9 @@ void WiiSocket::update(bool read, bool write, bool except)
int ret = (s32)accept(fd, NULL, 0);
ReturnValue = WiiSockMan::getNetErrorCode(ret, "SO_ACCEPT", false);
}
WiiSockMan::getInstance().addSocket(ReturnValue);
INFO_LOG(WII_IPC_NET, "IOCTL_SO_ACCEPT "
"BufferIn: (%08x, %i), BufferOut: (%08x, %i)",
BufferIn, BufferInSize, BufferOut, BufferOutSize);
@@ -410,26 +422,25 @@ void WiiSocket::update(bool read, bool write, bool except)
{
case IOCTLV_SO_SENDTO:
{
u32 flags = Memory::Read_U32(BufferIn2 + 0x04);
u32 has_destaddr = Memory::Read_U32(BufferIn2 + 0x08);
char * data = (char*)Memory::GetPointer(BufferIn);
u32 flags = Common::swap32(BufferIn2 + 0x04);
u32 has_destaddr = Common::swap32(BufferIn2 + 0x08);
// Act as non blocking when SO_MSG_NONBLOCK is specified
forceNonBlock = ((flags & SO_MSG_NONBLOCK) == SO_MSG_NONBLOCK);
// send/sendto only handles PEEK
flags &= SO_MSG_PEEK | SO_MSG_OOB;
// send/sendto only handles MSG_OOB
flags &= SO_MSG_OOB;
u8 destaddr[28];
struct sockaddr_in* addr = (struct sockaddr_in*)&destaddr;
sockaddr_in local_name;
if (has_destaddr)
{
Memory::ReadBigEData((u8*)&destaddr, BufferIn2 + 0x0C, BufferInSize2 - 0x0C);
addr->sin_family = addr->sin_family >> 8;
{
WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferIn2 + 0x0C);
WiiSockMan::Convert(*wii_name, local_name);
}
int ret = sendto(fd, data, BufferInSize, flags,
has_destaddr ? (struct sockaddr*)addr : NULL,
has_destaddr ? (struct sockaddr*)&local_name : NULL,
has_destaddr ? sizeof(sockaddr) : 0);
ReturnValue = WiiSockMan::getNetErrorCode(ret, "SO_SENDTO", true);
@@ -438,60 +449,60 @@ void WiiSocket::update(bool read, bool write, bool except)
has_destaddr ? "IOCTLV_SO_SENDTO " : "IOCTLV_SO_SEND ",
ReturnValue, fd, BufferIn, BufferInSize,
BufferIn2, BufferInSize2,
addr->sin_addr.s_addr & 0xFF,
(addr->sin_addr.s_addr >> 8) & 0xFF,
(addr->sin_addr.s_addr >> 16) & 0xFF,
(addr->sin_addr.s_addr >> 24) & 0xFF
local_name.sin_addr.s_addr & 0xFF,
(local_name.sin_addr.s_addr >> 8) & 0xFF,
(local_name.sin_addr.s_addr >> 16) & 0xFF,
(local_name.sin_addr.s_addr >> 24) & 0xFF
);
break;
}
case IOCTLV_SO_RECVFROM:
{
u32 sock = Memory::Read_U32(BufferIn);
u32 flags = Memory::Read_U32(BufferIn + 4);
char *buf = (char *)Memory::GetPointer(BufferOut);
int len = BufferOutSize;
struct sockaddr_in addr;
memset(&addr, 0, sizeof(sockaddr_in));
socklen_t fromlen = 0;
u32 flags = Memory::Read_U32(BufferIn + 0x04);
char * data = (char *)Memory::GetPointer(BufferOut);
int data_len = BufferOutSize;
sockaddr_in local_name;
memset(&local_name, 0, sizeof(sockaddr_in));
if (BufferOutSize2 != 0)
{
fromlen = BufferOutSize2 >= sizeof(struct sockaddr) ? BufferOutSize2 : sizeof(struct sockaddr);
WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferOut2);
WiiSockMan::Convert(*wii_name, local_name);
}
// Act as non blocking when SO_MSG_NONBLOCK is specified
forceNonBlock = ((flags & SO_MSG_NONBLOCK) == SO_MSG_NONBLOCK);
// recv/recvfrom only handles PEEK
// recv/recvfrom only handles PEEK/OOB
flags &= SO_MSG_PEEK | SO_MSG_OOB;
#ifdef _WIN32
if (flags & MSG_PEEK){
if (flags & SO_MSG_PEEK){
unsigned long totallen = 0;
ioctlsocket(sock, FIONREAD, &totallen);
ioctlsocket(fd, FIONREAD, &totallen);
ReturnValue = totallen;
break;
}
#endif
int ret = recvfrom(sock, buf, len, flags,
fromlen ? (struct sockaddr*) &addr : NULL,
fromlen ? &fromlen : 0);
ReturnValue = WiiSockMan::getNetErrorCode(ret, fromlen ? "SO_RECVFROM" : "SO_RECV", true);
socklen_t addrlen = sizeof(sockaddr_in);
int ret = recvfrom(fd, data, data_len, flags,
BufferOutSize2 ? (struct sockaddr*) &local_name : NULL,
BufferOutSize2 ? &addrlen : 0);
ReturnValue = WiiSockMan::getNetErrorCode(ret, BufferOutSize2 ? "SO_RECVFROM" : "SO_RECV", true);
INFO_LOG(WII_IPC_NET, "%s(%d, %p) Socket: %08X, Flags: %08X, "
"BufferIn: (%08x, %i), BufferIn2: (%08x, %i), "
"BufferOut: (%08x, %i), BufferOut2: (%08x, %i)",
fromlen ? "IOCTLV_SO_RECVFROM " : "IOCTLV_SO_RECV ",
ReturnValue, buf, sock, flags,
BufferOutSize2 ? "IOCTLV_SO_RECVFROM " : "IOCTLV_SO_RECV ",
ReturnValue, data, fd, flags,
BufferIn, BufferInSize, BufferIn2, BufferInSize2,
BufferOut, BufferOutSize, BufferOut2, BufferOutSize2);
if (BufferOutSize2 != 0)
{
addr.sin_family = (addr.sin_family << 8) | (BufferOutSize2&0xFF);
Memory::WriteBigEData((u8*)&addr, BufferOut2, BufferOutSize2);
WiiSockAddrIn* wii_name = (WiiSockAddrIn*)Memory::GetPointer(BufferOut2);
WiiSockMan::Convert(local_name, *wii_name, addrlen);
}
break;
}
@@ -506,7 +517,7 @@ void WiiSocket::update(bool read, bool write, bool except)
|| (!it->is_ssl && ReturnValue != -SO_EAGAIN && ReturnValue != -SO_EINPROGRESS && ReturnValue != -SO_EALREADY)
|| (it->is_ssl && ReturnValue != SSL_ERR_WAGAIN && ReturnValue != SSL_ERR_RAGAIN))
{
DEBUG_LOG(WII_IPC_NET, "IOCTL(V) Sock: %d ioctl/v: %d returned: %d nonBlock: %d forceNonBlock: %d",
DEBUG_LOG(WII_IPC_NET, "IOCTL(V) Sock: %08x ioctl/v: %d returned: %d nonBlock: %d forceNonBlock: %d",
fd, it->is_ssl ? it->ssl_type : it->net_type, ReturnValue, nonBlock, forceNonBlock);
WiiSockMan::EnqueueReply(it->_CommandAddress, ReturnValue);
it = pending_sockops.erase(it);
@@ -532,6 +543,15 @@ void WiiSocket::doSock(u32 _CommandAddress, SSL_IOCTL type)
pending_sockops.push_back(so);
}
void WiiSockMan::addSocket(s32 fd)
{
if (fd >= 0)
{
WiiSocket& sock = WiiSockets[fd];
sock.setFd(fd);
}
}
s32 WiiSockMan::newSocket(s32 af, s32 type, s32 protocol)
{
if (NetPlay::IsNetPlayRunning()
@@ -543,11 +563,7 @@ s32 WiiSockMan::newSocket(s32 af, s32 type, s32 protocol)
s32 fd = (s32)socket(af, type, protocol);
s32 ret = getNetErrorCode(fd, "newSocket", false);
if (ret >= 0)
{
WiiSocket& sock = WiiSockets[ret];
sock.setFd(ret);
}
addSocket(ret);
return ret;
}
+5 -1
View File
@@ -210,7 +210,10 @@ public:
static void Convert(sockaddr_in const & from, WiiSockAddrIn& to, s32 addrlen=-1);
// NON-BLOCKING FUNCTIONS
s32 newSocket(s32 af, s32 type, s32 protocol);
void addSocket(s32 fd);
s32 delSocket(s32 s);
s32 getLastNetError() {return errono_last;}
void setLastNetError(s32 error) {errono_last = error;}
void clean()
{
@@ -237,8 +240,9 @@ private:
WiiSockMan() {}; // Constructor? (the {} brackets) are needed here.
WiiSockMan(WiiSockMan const&); // Don't Implement
void operator=(WiiSockMan const&); // Don't implement
std::unordered_map<s32, WiiSocket> WiiSockets;
s32 errono_last;
};
#endif
+15 -2
View File
@@ -8,6 +8,7 @@
#include "IPC_HLE/WII_IPC_HLE_Device_usb.h"
#include "IPC_HLE/WII_IPC_HLE_WiiMote.h"
// for gcpad
#include "HW/SI.h"
#include "HW/SI_DeviceGCController.h"
#include "HW/SI_DeviceGCSteeringWheel.h"
#include "HW/SI_DeviceDanceMat.h"
@@ -187,6 +188,8 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
for (PadMapping i = 0; i < 4; i++)
packet >> m_pad_map[i];
UpdateDevices();
m_dialog->Update();
}
break;
@@ -233,8 +236,6 @@ unsigned int NetPlayClient::OnData(sf::Packet& packet)
packet >> g_NetPlaySettings.m_DSPEnableJIT;
packet >> g_NetPlaySettings.m_DSPHLE;
packet >> g_NetPlaySettings.m_WriteToMemcard;
for (unsigned int i = 0; i < 4; ++i)
packet >> g_NetPlaySettings.m_Controllers[i];
}
m_dialog->OnMsgStartGame();
@@ -422,6 +423,8 @@ bool NetPlayClient::StartGame(const std::string &path)
// boot game
m_dialog->BootGame(path);
UpdateDevices();
// temporary
NetWiimote nw;
for (unsigned int i = 0; i<4; ++i)
@@ -437,6 +440,16 @@ bool NetPlayClient::ChangeGame(const std::string&)
return true;
}
// called from ---NETPLAY--- thread
void NetPlayClient::UpdateDevices()
{
for (PadMapping i = 0; i < 4; i++)
{
// XXX: add support for other device types? does it matter?
SerialInterface::AddDevice(m_pad_map[i] > 0 ? SIDEVICE_GC_CONTROLLER : SIDEVICE_NONE, i);
}
}
// called from ---NETPLAY--- thread
void NetPlayClient::ClearBuffers()
{
+1
View File
@@ -117,6 +117,7 @@ protected:
PadMapping m_pad_map[4];
private:
void UpdateDevices();
void SendPadState(const PadMapping in_game_pad, const NetPad& np);
unsigned int OnData(sf::Packet& packet);
+1 -2
View File
@@ -14,7 +14,6 @@ struct NetSettings
bool m_DSPHLE;
bool m_DSPEnableJIT;
bool m_WriteToMemcard;
u8 m_Controllers[4];
};
struct Rpt : public std::vector<u8>
@@ -24,7 +23,7 @@ struct Rpt : public std::vector<u8>
typedef std::vector<Rpt> NetWiimote;
#define NETPLAY_VERSION "Dolphin NetPlay 2013-08-23"
#define NETPLAY_VERSION "Dolphin NetPlay 2013-08-31"
// messages
enum
-2
View File
@@ -441,8 +441,6 @@ bool NetPlayServer::StartGame(const std::string &path)
spac << m_settings.m_DSPEnableJIT;
spac << m_settings.m_DSPHLE;
spac << m_settings.m_WriteToMemcard;
for (unsigned int i = 0; i < 4; ++i)
spac << m_settings.m_Controllers[i];
std::lock_guard<std::recursive_mutex> lkp(m_crit.players);
std::lock_guard<std::recursive_mutex> lks(m_crit.send);
@@ -122,6 +122,10 @@ public:
void GetCarryAndClear(ARMReg reg);
void FinalizeCarry(ARMReg reg);
// TODO: This shouldn't be here
void StoreFromReg(ARMReg dest, ARMReg value, int accessSize, s32 offset);
void LoadToReg(ARMReg dest, ARMReg addr, int accessSize, s32 offset);
// OPCODES
void unknown_instruction(UGeckoInstruction _inst);
void Default(UGeckoInstruction _inst);
@@ -193,6 +197,7 @@ public:
void sthu(UGeckoInstruction _inst);
void stw(UGeckoInstruction _inst);
void stwu(UGeckoInstruction _inst);
void stwx(UGeckoInstruction _inst);
// Floating point
void fabsx(UGeckoInstruction _inst);
@@ -207,6 +212,7 @@ public:
// Floating point loadStore
void lfs(UGeckoInstruction _inst);
void lfd(UGeckoInstruction _inst);
void stfs(UGeckoInstruction _inst);
// Paired Singles
void ps_add(UGeckoInstruction _inst);
@@ -107,14 +107,11 @@ void JitArm::fsubx(UGeckoInstruction inst)
if (inst.Rc) Helper_UpdateCR1(vD);
}
// Breaks Animal Crossing
void JitArm::fmulsx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(FloatingPoint)
Default(inst); return;
ARMReg vA = fpr.R0(inst.FA);
ARMReg vC = fpr.R0(inst.FC);
ARMReg vD0 = fpr.R0(inst.FD);
@@ -122,6 +119,7 @@ void JitArm::fmulsx(UGeckoInstruction inst)
VMUL(vD0, vA, vC);
VMOV(vD1, vD0);
fpr.Flush(); // Shouldn't be needed. Missing a flush somewhere
if (inst.Rc) Helper_UpdateCR1(vD0);
}
void JitArm::fmulx(UGeckoInstruction inst)
@@ -31,12 +31,36 @@
#include "JitRegCache.h"
#include "JitAsm.h"
#ifdef ANDROID
#define FASTMEM 0
#else
#define FASTMEM 1
#endif
void JitArm::stb(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(LoadStore)
ARMReg RS = gpr.R(inst.RS);
#if 0 // FASTMEM
// R10 contains the dest address
ARMReg Value = R11;
ARMReg RA;
if (inst.RA)
RA = gpr.R(inst.RA);
MOV(Value, RS);
if (inst.RA)
{
MOVI2R(R10, inst.SIMM_16, false);
ADD(R10, R10, RA);
}
else
{
MOVI2R(R10, (u32)inst.SIMM_16, false);
NOP(1);
}
StoreFromReg(R10, Value, 16, 0);
#else
ARMReg ValueReg = gpr.GetReg();
ARMReg Addr = gpr.GetReg();
ARMReg Function = gpr.GetReg();
@@ -58,6 +82,7 @@ void JitArm::stb(UGeckoInstruction inst)
BL(Function);
POP(4, R0, R1, R2, R3);
gpr.Unlock(ValueReg, Addr, Function);
#endif
}
void JitArm::stbu(UGeckoInstruction inst)
@@ -97,6 +122,25 @@ void JitArm::sth(UGeckoInstruction inst)
JITDISABLE(LoadStore)
ARMReg RS = gpr.R(inst.RS);
#if 0 // FASTMEM
// R10 contains the dest address
ARMReg Value = R11;
ARMReg RA;
if (inst.RA)
RA = gpr.R(inst.RA);
MOV(Value, RS);
if (inst.RA)
{
MOVI2R(R10, inst.SIMM_16, false);
ADD(R10, R10, RA);
}
else
{
MOVI2R(R10, (u32)inst.SIMM_16, false);
NOP(1);
}
StoreFromReg(R10, Value, 16, 0);
#else
ARMReg ValueReg = gpr.GetReg();
ARMReg Addr = gpr.GetReg();
ARMReg Function = gpr.GetReg();
@@ -118,6 +162,7 @@ void JitArm::sth(UGeckoInstruction inst)
BL(Function);
POP(4, R0, R1, R2, R3);
gpr.Unlock(ValueReg, Addr, Function);
#endif
}
void JitArm::sthu(UGeckoInstruction inst)
{
@@ -158,6 +203,29 @@ void JitArm::stw(UGeckoInstruction inst)
JITDISABLE(LoadStore)
ARMReg RS = gpr.R(inst.RS);
#if FASTMEM
// R10 contains the dest address
if (Core::g_CoreStartupParameter.bFastmem)
{
ARMReg Value = R11;
ARMReg RA;
if (inst.RA)
RA = gpr.R(inst.RA);
MOV(Value, RS);
if (inst.RA)
{
MOVI2R(R10, inst.SIMM_16, false);
ADD(R10, R10, RA);
}
else
{
MOVI2R(R10, (u32)inst.SIMM_16, false);
NOP(1);
}
StoreFromReg(R10, Value, 32, 0);
}
else
#endif
{
ARMReg ValueReg = gpr.GetReg();
ARMReg Addr = gpr.GetReg();
@@ -214,6 +282,113 @@ void JitArm::stwu(UGeckoInstruction inst)
gpr.Unlock(ValueReg, Addr, Function);
}
void JitArm::stwx(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(LoadStore)
u32 a = inst.RA, b = inst.RB, s = inst.RB;
if (a) {
// Doesn't work
Default(inst); return;
}
ARMReg RB = gpr.R(b);
ARMReg RS = gpr.R(s);
ARMReg ValueReg = gpr.GetReg();
ARMReg Addr = gpr.GetReg();
ARMReg Function = gpr.GetReg();
if (a)
ADD(Addr, gpr.R(a), RB);
else
MOV(Addr, RB);
MOV(ValueReg, RS);
fpr.Flush();
MOVI2R(Function, (u32)&Memory::Write_U32);
PUSH(4, R0, R1, R2, R3);
MOV(R0, ValueReg);
MOV(R1, Addr);
BL(Function);
POP(4, R0, R1, R2, R3);
gpr.Unlock(ValueReg, Addr, Function);
}
void JitArm::StoreFromReg(ARMReg dest, ARMReg value, int accessSize, s32 offset)
{
ARMReg rA = gpr.GetReg();
// All this gets replaced on backpatch
MOVI2R(rA, Memory::MEMVIEW32_MASK, false); // 1-2
AND(dest, dest, rA); // 3
MOVI2R(rA, (u32)Memory::base, false); // 4-5
ADD(dest, dest, rA); // 6
switch (accessSize)
{
case 32:
REV(value, value); // 7
break;
case 16:
REV16(value, value);
break;
case 8:
NOP(1);
break;
}
switch (accessSize)
{
case 32:
STR(value, dest); // 8
break;
case 16:
STRH(value, dest);
break;
case 8:
STRB(value, dest);
break;
}
gpr.Unlock(rA);
}
void JitArm::LoadToReg(ARMReg dest, ARMReg addr, int accessSize, s32 offset)
{
ARMReg rA = gpr.GetReg();
MOVI2R(rA, offset, false); // -3
ADD(addr, addr, rA); // - 1
// All this gets replaced on backpatch
MOVI2R(rA, Memory::MEMVIEW32_MASK, false); // 2
AND(addr, addr, rA); // 3
MOVI2R(rA, (u32)Memory::base, false); // 5
ADD(addr, addr, rA); // 6
switch (accessSize)
{
case 32:
LDR(dest, addr); // 7
break;
case 16:
LDRH(dest, addr);
break;
case 8:
LDRB(dest, addr);
break;
}
switch (accessSize)
{
case 32:
REV(dest, dest); // 9
break;
case 16:
REV16(dest, dest);
break;
case 8:
NOP(1);
break;
}
gpr.Unlock(rA);
}
void JitArm::lbz(UGeckoInstruction inst)
{
INSTRUCTION_START
@@ -225,6 +400,24 @@ void JitArm::lbz(UGeckoInstruction inst)
LDR(rA, R9, PPCSTATE_OFF(Exceptions));
CMP(rA, EXCEPTION_DSI);
FixupBranch DoNotLoad = B_CC(CC_EQ);
#if FASTMEM
// Backpatch route
// Gets loaded in to RD
// Address is in R10
if (Core::g_CoreStartupParameter.bFastmem)
{
gpr.Unlock(rA, rB);
if (inst.RA)
{
ARMReg RA = gpr.R(inst.RA);
MOV(R10, RA); // - 4
}
else
MOV(R10, 0); // - 4
LoadToReg(RD, R10, 8, inst.SIMM_16);
}
else
#endif
{
if (inst.RA)
{
@@ -258,6 +451,22 @@ void JitArm::lhz(UGeckoInstruction inst)
LDR(rA, R9, PPCSTATE_OFF(Exceptions));
CMP(rA, EXCEPTION_DSI);
FixupBranch DoNotLoad = B_CC(CC_EQ);
#if FASTMEM
// Backpatch route
// Gets loaded in to RD
// Address is in R10
gpr.Unlock(rA, rB);
if (inst.RA)
{
ARMReg RA = gpr.R(inst.RA);
MOV(R10, RA); // - 4
}
else
MOV(R10, 0); // - 4
LoadToReg(RD, R10, 16, (u32)inst.SIMM_16);
#else
if (inst.RA)
{
MOVI2R(rB, inst.SIMM_16);
@@ -275,6 +484,7 @@ void JitArm::lhz(UGeckoInstruction inst)
POP(4, R0, R1, R2, R3);
MOV(RD, rA);
gpr.Unlock(rA, rB);
#endif
SetJumpTarget(DoNotLoad);
}
void JitArm::lha(UGeckoInstruction inst)
@@ -321,6 +531,25 @@ void JitArm::lwz(UGeckoInstruction inst)
LDR(rA, R9, PPCSTATE_OFF(Exceptions));
CMP(rA, EXCEPTION_DSI);
FixupBranch DoNotLoad = B_CC(CC_EQ);
#if FASTMEM
// Backpatch route
// Gets loaded in to RD
// Address is in R10
if (Core::g_CoreStartupParameter.bFastmem)
{
gpr.Unlock(rA, rB);
if (inst.RA)
{
ARMReg RA = gpr.R(inst.RA);
MOV(R10, RA); // - 4
}
else
MOV(R10, 0); // - 4
LoadToReg(RD, R10, 32, (u32)inst.SIMM_16);
}
else
#endif
{
if (inst.RA)
{
@@ -381,6 +610,24 @@ void JitArm::lwzx(UGeckoInstruction inst)
LDR(rA, R9, PPCSTATE_OFF(Exceptions));
CMP(rA, EXCEPTION_DSI);
FixupBranch DoNotLoad = B_CC(CC_EQ);
#if FASTMEM
// Backpatch route
// Gets loaded in to RD
// Address is in R10
if (Core::g_CoreStartupParameter.bFastmem)
{
gpr.Unlock(rA, rB);
if (inst.RA)
{
ARMReg RA = gpr.R(inst.RA);
ADD(R10, RA, RB); // - 4
}
else
MOV(R10, RB); // -4
LoadToReg(RD, R10, 32, 0);
}
else
#endif
{
if (inst.RA)
{
@@ -39,6 +39,9 @@ void JitArm::lfs(UGeckoInstruction inst)
ARMReg rA = gpr.GetReg();
ARMReg rB = gpr.GetReg();
fpr.Flush();
LDR(rA, R9, PPCSTATE_OFF(Exceptions));
CMP(rA, EXCEPTION_DSI);
FixupBranch DoNotLoad = B_CC(CC_EQ);
@@ -52,7 +55,6 @@ void JitArm::lfs(UGeckoInstruction inst)
else
MOVI2R(rB, (u32)inst.SIMM_16);
fpr.Flush();
MOVI2R(rA, (u32)&Memory::Read_F32);
PUSH(4, R0, R1, R2, R3);
@@ -61,6 +63,9 @@ void JitArm::lfs(UGeckoInstruction inst)
ARMReg v0 = fpr.R0(inst.FD);
ARMReg v1 = fpr.R1(inst.FD);
#if !defined(__ARM_PCS_VFP) // SoftFP returns in R0
VMOV(S0, R0);
#endif
VCVT(v0, S0, 0);
VCVT(v1, S0, 0);
@@ -77,6 +82,9 @@ void JitArm::lfd(UGeckoInstruction inst)
ARMReg rA = gpr.GetReg();
ARMReg rB = gpr.GetReg();
fpr.Flush();
LDR(rA, R9, PPCSTATE_OFF(Exceptions));
CMP(rA, EXCEPTION_DSI);
FixupBranch DoNotLoad = B_CC(CC_EQ);
@@ -90,7 +98,6 @@ void JitArm::lfd(UGeckoInstruction inst)
else
MOVI2R(rB, (u32)inst.SIMM_16);
fpr.Flush();
MOVI2R(rA, (u32)&Memory::Read_F64);
PUSH(4, R0, R1, R2, R3);
@@ -98,10 +105,48 @@ void JitArm::lfd(UGeckoInstruction inst)
BL(rA);
ARMReg v0 = fpr.R0(inst.FD);
#if !defined(__ARM_PCS_VFP) // SoftFP returns in R0 and R1
VMOV(v0, R0);
#else
VMOV(v0, D0);
#endif
POP(4, R0, R1, R2, R3);
gpr.Unlock(rA, rB);
SetJumpTarget(DoNotLoad);
}
void JitArm::stfs(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(LoadStoreFloating)
ARMReg rA = gpr.GetReg();
ARMReg rB = gpr.GetReg();
ARMReg v0 = fpr.R0(inst.FS);
VCVT(S0, v0, 0);
fpr.Flush();
if (inst.RA)
{
MOVI2R(rB, inst.SIMM_16);
ARMReg RA = gpr.R(inst.RA);
ADD(rB, rB, RA);
}
else
MOVI2R(rB, (u32)inst.SIMM_16);
MOVI2R(rA, (u32)&Memory::Write_U32);
PUSH(4, R0, R1, R2, R3);
VMOV(R0, S0);
MOV(R1, rB);
BL(rA);
POP(4, R0, R1, R2, R3);
gpr.Unlock(rA, rB);
}
@@ -102,7 +102,7 @@ static GekkoOPTemplate primarytable[] =
{50, &JitArm::lfd}, //"lfd", OPTYPE_LOADFP, FL_IN_A}},
{51, &JitArm::Default}, //"lfdu", OPTYPE_LOADFP, FL_OUT_A | FL_IN_A}},
{52, &JitArm::Default}, //"stfs", OPTYPE_STOREFP, FL_IN_A}},
{52, &JitArm::stfs}, //"stfs", OPTYPE_STOREFP, FL_IN_A}},
{53, &JitArm::Default}, //"stfsu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}},
{54, &JitArm::Default}, //"stfd", OPTYPE_STOREFP, FL_IN_A}},
{55, &JitArm::Default}, //"stfdu", OPTYPE_STOREFP, FL_OUT_A | FL_IN_A}},
@@ -249,7 +249,7 @@ static GekkoOPTemplate table31[] =
{597, &JitArm::Default}, //"lswi", OPTYPE_LOAD, FL_EVIL | FL_IN_AB | FL_OUT_D}},
//store word
{151, &JitArm::Default}, //"stwx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
{151, &JitArm::stwx}, //"stwx", OPTYPE_STORE, FL_IN_A0 | FL_IN_B}},
{183, &JitArm::Default}, //"stwux", OPTYPE_STORE, FL_OUT_A | FL_IN_A | FL_IN_B}},
//store halfword
@@ -293,7 +293,7 @@ static GekkoOPTemplate table31[] =
{659, &JitArm::Default}, //"mfsrin", OPTYPE_SYSTEM, FL_OUT_D, 2}},
{4, &JitArm::Break}, //"tw", OPTYPE_SYSTEM, FL_ENDBLOCK, 1}},
{598, &JitArm::Default}, //"sync", OPTYPE_SYSTEM, 0, 2}},
{598, &JitArm::DoNothing}, //"sync", OPTYPE_SYSTEM, 0, 2}},
{982, &JitArm::icbi}, //"icbi", OPTYPE_SYSTEM, FL_ENDBLOCK, 3}},
// Unused instructions on GC
@@ -44,7 +44,12 @@ JitArmAsmRoutineManager asm_routines;
void JitArmAsmRoutineManager::Generate()
{
enterCode = GetCodePtr();
PUSH(2, R11, _LR); // R11 is frame pointer in Debug.
PUSH(9, R4, R5, R6, R7, R8, R9, R10, R11, _LR);
// Take care to 8-byte align stack for function calls.
// We are misaligned here because of an odd number of args for PUSH.
// It's not like x86 where you need to account for an extra 4 bytes
// consumed by CALL.
SUB(_SP, _SP, 4);
MOVI2R(R0, (u32)&CoreTiming::downcount);
MOVI2R(R9, (u32)&PowerPC::ppcState.spr[0]);
@@ -129,7 +134,9 @@ void JitArmAsmRoutineManager::Generate()
SetJumpTarget(Exit);
POP(2, R11, _PC);
ADD(_SP, _SP, 4);
POP(9, R4, R5, R6, R7, R8, R9, R10, R11, _PC); // Returns
FlushIcache();
}
+17 -30
View File
@@ -5,7 +5,7 @@
#include "NANDContentLoader.h"
#include <algorithm>
#include <cctype>
#include <cctype>
#include "Crypto/aes.h"
#include "MathUtil.h"
#include "FileUtil.h"
@@ -42,7 +42,7 @@ void CSharedContent::UpdateLocation()
CSharedContent::~CSharedContent()
{}
std::string CSharedContent::GetFilenameFromSHA1(u8* _pHash)
std::string CSharedContent::GetFilenameFromSHA1(const u8* _pHash)
{
for (size_t i=0; i<m_Elements.size(); i++)
{
@@ -58,7 +58,7 @@ std::string CSharedContent::GetFilenameFromSHA1(u8* _pHash)
return "unk";
}
std::string CSharedContent::AddSharedContent(u8* _pHash)
std::string CSharedContent::AddSharedContent(const u8* _pHash)
{
std::string szFilename = GetFilenameFromSHA1(_pHash);
if (strcasecmp(szFilename.c_str(), "unk") == 0)
@@ -170,8 +170,11 @@ const SNANDContent* CNANDContentLoader::GetContentByIndex(int _Index) const
{
for (size_t i=0; i<m_Content.size(); i++)
{
if (m_Content[i].m_Index == _Index)
return &m_Content[i];
const SNANDContent* pContent = &m_Content[i];
if (pContent->m_Index == _Index)
{
return pContent;
}
}
return NULL;
}
@@ -210,8 +213,8 @@ bool CNANDContentLoader::Initialize(const std::string& _rName)
File::IOFile pTMDFile(TMDFileName, "rb");
if (!pTMDFile)
{
DEBUG_LOG(DISCIO, "CreateFromDirectory: error opening %s",
TMDFileName.c_str());
WARN_LOG(DISCIO, "CreateFromDirectory: error opening %s",
TMDFileName.c_str());
return false;
}
u32 pTMDSize = (u32)File::GetSize(TMDFileName);
@@ -219,8 +222,7 @@ bool CNANDContentLoader::Initialize(const std::string& _rName)
pTMDFile.ReadBytes(pTMD, (size_t)pTMDSize);
pTMDFile.Close();
}
if (!pTMD)
return false;
memcpy(m_TMDView, pTMD + 0x180, TMD_VIEW_SIZE);
memcpy(m_TMDHeader, pTMD, TMD_HEADER_SIZE);
@@ -262,35 +264,20 @@ bool CNANDContentLoader::Initialize(const std::string& _rName)
}
rContent.m_pData = NULL;
char szFilename[1024];
if (rContent.m_Type & 0x8000) // shared app
{
std::string Filename = CSharedContent::AccessInstance().GetFilenameFromSHA1(rContent.m_SHA1Hash);
strcpy(szFilename, Filename.c_str());
rContent.m_Filename = CSharedContent::AccessInstance().GetFilenameFromSHA1(rContent.m_SHA1Hash);
}
else
{
sprintf(szFilename, "%s/%08x.app", m_Path.c_str(), rContent.m_ContentID);
rContent.m_Filename = StringFromFormat("%s/%08x.app", m_Path.c_str(), rContent.m_ContentID);
}
INFO_LOG(DISCIO, "NANDContentLoader: load %s", szFilename);
File::IOFile pFile(szFilename, "rb");
if (pFile)
// Be graceful about incorrect tmds.
if (File::Exists(rContent.m_Filename))
{
const u64 ContentSize = File::GetSize(szFilename);
rContent.m_pData = new u8[(u32)ContentSize];
_dbg_assert_msg_(BOOT, rContent.m_Size==ContentSize, "TMDLoader: Incorrect filesize (%s %i). Your NAND dump may be corrupt.", szFilename, i);
pFile.ReadBytes(rContent.m_pData, (size_t)ContentSize);
}
else
{
ERROR_LOG(DISCIO, "NANDContentLoader: error opening %s", szFilename);
delete [] pTMD;
return false;
rContent.m_Size = (u32) File::GetSize(rContent.m_Filename);
}
}
@@ -493,7 +480,7 @@ u64 CNANDContentManager::Install_WiiWAD(std::string &fileName)
for (u32 i = 0; i < ContentLoader.GetContentSize(); i++)
{
SNANDContent Content = ContentLoader.GetContent()[i];
const SNANDContent& Content = ContentLoader.GetContent()[i];
pTMDFile.WriteBytes(Content.m_Header, INANDContentLoader::CONTENT_HEADER_SIZE);
+4 -2
View File
@@ -13,6 +13,7 @@
#include "Blob.h"
#include "Volume.h"
#include "NandPaths.h"
#include "FileUtil.h"
namespace DiscIO
{
@@ -26,6 +27,7 @@ struct SNANDContent
u8 m_SHA1Hash[20];
u8 m_Header[36]; //all of the above
std::string m_Filename;
u8* m_pData;
};
@@ -95,8 +97,8 @@ public:
static CSharedContent& AccessInstance() { return m_Instance; }
std::string GetFilenameFromSHA1(u8* _pHash);
std::string AddSharedContent(u8* _pHash);
std::string GetFilenameFromSHA1(const u8* _pHash);
std::string AddSharedContent(const u8* _pHash);
void UpdateLocation();
private:
+71 -31
View File
@@ -1,3 +1,7 @@
if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin")
option(SKIP_POSTPROCESS_BUNDLE "Skip postprocessing bundle for redistributability" OFF)
endif()
set(LIBS core
${LZO}
discio
@@ -170,6 +174,13 @@ if(USE_UPNP)
set(LIBS ${LIBS} miniupnpc)
endif()
include(FindGettext)
if(GETTEXT_FOUND AND wxWidgets_FOUND)
file(GLOB LINGUAS ${CMAKE_SOURCE_DIR}/Languages/po/*.po)
add_custom_target(translations ALL)
GETTEXT_CREATE_TRANSLATIONS(${CMAKE_SOURCE_DIR}/Languages/po/dolphin-emu.pot ${LINGUAS})
endif()
if(ANDROID)
set(DOLPHIN_EXE main)
add_library(${DOLPHIN_EXE} SHARED ${SRCS})
@@ -217,47 +228,76 @@ else()
MACOSX_BUNDLE_INFO_PLIST ${CMAKE_CURRENT_SOURCE_DIR}/Info.plist.in
)
# Fix up the bundle after it is finished.
# There does not seem to be an easy way to run CMake commands post-build,
# so we invoke CMake again on a generated script.
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/postprocess_bundle.cmake "
include(BundleUtilities)
message(\"Fixing up application bundle: ${BUNDLE_PATH}\")
set(BU_CHMOD_BUNDLE_ITEMS ON)
fixup_bundle(\"${BUNDLE_PATH}\" \"\" \"\")
")
add_custom_command(TARGET ${DOLPHIN_EXE} POST_BUILD
COMMAND ${CMAKE_COMMAND} -P postprocess_bundle.cmake
)
if(NOT SKIP_POSTPROCESS_BUNDLE)
# Fix up the bundle after it is finished.
# There does not seem to be an easy way to run CMake commands post-build,
# so we invoke CMake again on a generated script.
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/postprocess_bundle.cmake "
include(BundleUtilities)
message(\"Fixing up application bundle: ${BUNDLE_PATH}\")
message(\"(Note: This is only necessary to produce a redistributable binary.\")
message(\"To skip, pass -DSKIP_POSTPROCESS_BUNDLE=1 to cmake.)\")
set(BU_CHMOD_BUNDLE_ITEMS ON)
fixup_bundle(\"${BUNDLE_PATH}\" \"\" \"\")
")
add_custom_command(TARGET ${DOLPHIN_EXE} POST_BUILD
COMMAND ${CMAKE_COMMAND} -P postprocess_bundle.cmake
)
endif()
# Copy data files into application bundle.
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/copy_data_into_bundle.cmake "
file(INSTALL ${CMAKE_SOURCE_DIR}/Data/Sys ${CMAKE_SOURCE_DIR}/Data/User
DESTINATION ${BUNDLE_PATH}/Contents/Resources
)
file(GLOB TRANSLATION_FILES RELATIVE ${CMAKE_BINARY_DIR}
${CMAKE_BINARY_DIR}/*.gmo
)
foreach(TRANSLATION_FILE \${TRANSLATION_FILES})
string(REPLACE \".gmo\" \".lproj\" TRANSLATION_DIR
\${TRANSLATION_FILE}
)
# It would be better to copy to the new name as a single action,
# but I can't figure out a way to let CMake do that.
file(COPY ${CMAKE_BINARY_DIR}/\${TRANSLATION_FILE}
DESTINATION ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}
NO_SOURCE_PERMISSIONS
)
file(RENAME
${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}/\${TRANSLATION_FILE}
${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}/dolphin-emu.mo
)
endforeach(TRANSLATION_FILE)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/did_copy_data_into_bundle \"\")
")
add_custom_target(CopyDataIntoBundle ALL
add_custom_command(OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/did_copy_data_into_bundle
COMMAND ${CMAKE_COMMAND} -P copy_data_into_bundle.cmake
DEPENDS ${CMAKE_SOURCE_DIR}/Data/Sys ${CMAKE_SOURCE_DIR}/Data/User
VERBATIM
)
add_custom_target(CopyDataIntoBundle ALL
DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/did_copy_data_into_bundle
)
if(GETTEXT_FOUND AND wxWidgets_FOUND)
file(WRITE ${CMAKE_CURRENT_BINARY_DIR}/copy_translations_into_bundle.cmake "
file(GLOB TRANSLATION_FILES RELATIVE ${CMAKE_CURRENT_BINARY_DIR}
${CMAKE_CURRENT_BINARY_DIR}/*.gmo
)
foreach(TRANSLATION_FILE \${TRANSLATION_FILES})
string(REPLACE \".gmo\" \".lproj\" TRANSLATION_DIR
\${TRANSLATION_FILE}
)
# It would be better to copy to the new name as a single action,
# but I can't figure out a way to let CMake do that.
file(COPY ${CMAKE_CURRENT_BINARY_DIR}/\${TRANSLATION_FILE}
DESTINATION ${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}
NO_SOURCE_PERMISSIONS
)
file(RENAME
${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}/\${TRANSLATION_FILE}
${BUNDLE_PATH}/Contents/Resources/\${TRANSLATION_DIR}/dolphin-emu.mo
)
endforeach(TRANSLATION_FILE)
")
file(GLOB PO_FILES RELATIVE ${CMAKE_SOURCE_DIR}/Languages/po
${CMAKE_SOURCE_DIR}/Languages/po/*.po
)
string(REPLACE .po .gmo GMO_FILES "${PO_FILES}")
add_custom_command(OUTPUT ${BUNDLE_PATH}/Contents/Resources/en.lproj
COMMAND ${CMAKE_COMMAND} -P copy_translations_into_bundle.cmake
DEPENDS ${GMO_FILES}
${CMAKE_SOURCE_DIR}/Data/Sys ${CMAKE_SOURCE_DIR}/Data/User
VERBATIM
)
add_custom_target(CopyTranslationsIntoBundle ALL
DEPENDS ${BUNDLE_PATH}/Contents/Resources/en.lproj
)
endif()
# Install bundle into systemwide /Applications directory.
install(DIRECTORY ${BUNDLE_PATH} DESTINATION /Applications
+2 -2
View File
@@ -502,7 +502,7 @@ void CConfigMain::InitializeGUITooltips()
InterfaceLang->SetToolTip(_("Change the language of the user interface.\nRequires restart."));
// Audio tooltips
DSPThread->SetToolTip(_("Run DSP HLE and LLE on a dedicated thread (not recommended: might cause audio glitches with HLE and freezes with LLE)."));
DSPThread->SetToolTip(_("Run DSP LLE on a dedicated thread (not recommended: might cause freezes)."));
BackendSelection->SetToolTip(_("Changing this will have no effect while the emulator is running!"));
// Gamecube - Devices
@@ -643,7 +643,7 @@ void CConfigMain::CreateGUIControls()
// Audio page
DSPEngine = new wxRadioBox(AudioPage, ID_DSPENGINE, _("DSP Emulator Engine"),
wxDefaultPosition, wxDefaultSize, arrayStringFor_DSPEngine, 0, wxRA_SPECIFY_ROWS);
DSPThread = new wxCheckBox(AudioPage, ID_DSPTHREAD, _("DSP on Dedicated Thread"));
DSPThread = new wxCheckBox(AudioPage, ID_DSPTHREAD, _("DSPLLE on Separate Thread"));
DumpAudio = new wxCheckBox(AudioPage, ID_DUMP_AUDIO, _("Dump Audio"),
wxDefaultPosition, wxDefaultSize, 0, wxDefaultValidator);
DPL2Decoder = new wxCheckBox(AudioPage, ID_DPL2DECODER, _("Dolby Pro Logic II decoder"));
+37 -35
View File
@@ -216,39 +216,39 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
case IDM_COPYCODE:
{
char disasm[256];
debugger->disasm(selection, disasm, 256);
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(disasm)));
char disasm[256];
debugger->disasm(selection, disasm, 256);
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(disasm)));
}
break;
case IDM_COPYHEX:
{
char temp[24];
sprintf(temp, "%08x", debugger->readInstruction(selection));
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp)));
char temp[24];
sprintf(temp, "%08x", debugger->readInstruction(selection));
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(temp)));
}
break;
case IDM_COPYFUNCTION:
{
Symbol *symbol = symbol_db->GetSymbolFromAddr(selection);
if (symbol)
{
std::string text;
text = text + symbol->name + "\r\n";
// we got a function
u32 start = symbol->address;
u32 end = start + symbol->size;
for (u32 addr = start; addr != end; addr += 4)
Symbol *symbol = symbol_db->GetSymbolFromAddr(selection);
if (symbol)
{
char disasm[256];
debugger->disasm(addr, disasm, 256);
text = text + StringFromFormat("%08x: ", addr) + disasm + "\r\n";
std::string text;
text = text + symbol->name + "\r\n";
// we got a function
u32 start = symbol->address;
u32 end = start + symbol->size;
for (u32 addr = start; addr != end; addr += 4)
{
char disasm[256];
debugger->disasm(addr, disasm, 256);
text = text + StringFromFormat("%08x: ", addr) + disasm + "\r\n";
}
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(text)));
}
wxTheClipboard->SetData(new wxTextDataObject(StrToWxStr(text)));
}
}
break;
#endif
@@ -275,10 +275,12 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
case IDM_FOLLOWBRANCH:
{
u32 dest = AddrToBranch(selection);
if (dest)
Center(dest);
RaiseEvent();
u32 dest = AddrToBranch(selection);
if (dest)
{
Center(dest);
RaiseEvent();
}
}
break;
@@ -289,19 +291,19 @@ void CCodeView::OnPopupMenu(wxCommandEvent& event)
case IDM_RENAMESYMBOL:
{
Symbol *symbol = symbol_db->GetSymbolFromAddr(selection);
if (symbol)
{
wxTextEntryDialog input_symbol(this, StrToWxStr("Rename symbol:"),
wxGetTextFromUserPromptStr,
StrToWxStr(symbol->name));
if (input_symbol.ShowModal() == wxID_OK)
Symbol *symbol = symbol_db->GetSymbolFromAddr(selection);
if (symbol)
{
symbol->name = WxStrToStr(input_symbol.GetValue());
Refresh(); // Redraw to show the renamed symbol
wxTextEntryDialog input_symbol(this, StrToWxStr("Rename symbol:"),
wxGetTextFromUserPromptStr,
StrToWxStr(symbol->name));
if (input_symbol.ShowModal() == wxID_OK)
{
symbol->name = WxStrToStr(input_symbol.GetValue());
Refresh(); // Redraw to show the renamed symbol
}
Host_NotifyMapLoaded();
}
Host_NotifyMapLoaded();
}
}
break;
+2
View File
@@ -152,6 +152,7 @@ BEGIN_EVENT_TABLE(CFrame, CRenderFrame)
EVT_MENU(wxID_OPEN, CFrame::OnOpen)
EVT_MENU(wxID_EXIT, CFrame::OnQuit)
EVT_MENU(IDM_HELPWEBSITE, CFrame::OnHelp)
EVT_MENU(IDM_HELPONLINEDOCS, CFrame::OnHelp)
EVT_MENU(IDM_HELPGOOGLECODE, CFrame::OnHelp)
EVT_MENU(wxID_ABOUT, CFrame::OnHelp)
EVT_MENU(wxID_REFRESH, CFrame::OnRefresh)
@@ -191,6 +192,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_EXPORTALLSAVE, CFrame::OnExportAllSaves)
EVT_MENU(IDM_CHEATS, CFrame::OnShow_CheatsWindow)
EVT_MENU(IDM_CHANGEDISC, CFrame::OnChangeDisc)
EVT_MENU(IDM_MENU_INSTALLWAD, CFrame::OnInstallWAD)
+1
View File
@@ -324,6 +324,7 @@ private:
void OnMemcard(wxCommandEvent& event); // Misc
void OnImportSave(wxCommandEvent& event);
void OnExportAllSaves(wxCommandEvent& event);
void OnNetPlay(wxCommandEvent& event);
+14 -6
View File
@@ -190,7 +190,8 @@ void CFrame::CreateMenu()
// Tools menu
wxMenu* toolsMenu = new wxMenu;
toolsMenu->Append(IDM_MEMCARD, _("&Memcard Manager (GC)"));
toolsMenu->Append(IDM_IMPORTSAVE, _("Wii Save Import"));
toolsMenu->Append(IDM_IMPORTSAVE, _("Import Wii Save"));
toolsMenu->Append(IDM_EXPORTALLSAVE, _("Export All Wii Saves"));
toolsMenu->Append(IDM_CHEATS, _("&Cheats Manager"));
toolsMenu->Append(IDM_NETPLAY, _("Start &NetPlay"));
@@ -296,6 +297,7 @@ void CFrame::CreateMenu()
// Re-enable when there's something useful to display */
// helpMenu->Append(wxID_HELP, _("&Help"));
helpMenu->Append(IDM_HELPWEBSITE, _("Dolphin &Web Site"));
helpMenu->Append(IDM_HELPONLINEDOCS, _("Online &Documentation"));
helpMenu->Append(IDM_HELPGOOGLECODE, _("Dolphin at &Google Code"));
helpMenu->AppendSeparator();
helpMenu->Append(wxID_ABOUT, _("&About..."));
@@ -1254,10 +1256,13 @@ void CFrame::OnHelp(wxCommandEvent& event)
}
break;
case IDM_HELPWEBSITE:
WxUtils::Launch("http://dolphin-emu.org/");
WxUtils::Launch("https://dolphin-emu.org/");
break;
case IDM_HELPONLINEDOCS:
WxUtils::Launch("https://dolphin-emu.org/docs/guides/");
break;
case IDM_HELPGOOGLECODE:
WxUtils::Launch("http://code.google.com/p/dolphin-emu/");
WxUtils::Launch("https://code.google.com/p/dolphin-emu/");
break;
}
}
@@ -1310,6 +1315,11 @@ void CFrame::OnMemcard(wxCommandEvent& WXUNUSED (event))
MemcardManager.ShowModal();
}
void CFrame::OnExportAllSaves(wxCommandEvent& WXUNUSED (event))
{
CWiiSaveCrypted::ExportAllSaves();
}
void CFrame::OnImportSave(wxCommandEvent& WXUNUSED (event))
{
wxString path = wxFileSelector(_("Select the save file"),
@@ -1320,9 +1330,7 @@ void CFrame::OnImportSave(wxCommandEvent& WXUNUSED (event))
if (!path.IsEmpty())
{
// TODO: Does this actually need to be dynamically allocated for some reason?
CWiiSaveCrypted* saveFile = new CWiiSaveCrypted(WxStrToStr(path).c_str());
delete saveFile;
CWiiSaveCrypted::ImportWiiSave(WxStrToStr(path).c_str());
}
}
+1 -2
View File
@@ -969,8 +969,7 @@ void CGameListCtrl::OnExportSave(wxCommandEvent& WXUNUSED (event))
if (Iso->GetTitleID((u8*)&title))
{
title = Common::swap64(title);
CWiiSaveCrypted* exportSave = new CWiiSaveCrypted("", title);
delete exportSave;
CWiiSaveCrypted::ExportWiiSave(title);
}
delete Iso;
}
+2
View File
@@ -118,6 +118,7 @@ enum
IDM_PURGECACHE,
IDM_HELPWEBSITE, // Help menu
IDM_HELPONLINEDOCS,
IDM_HELPGOOGLECODE,
IDM_CONFIG_GFX_BACKEND,
@@ -231,6 +232,7 @@ enum
IDM_OPENSAVEFOLDER,
IDM_EXPORTSAVE,
IDM_IMPORTSAVE,
IDM_EXPORTALLSAVE,
IDM_SETDEFAULTGCM,
IDM_DELETEGCM,
IDM_COMPRESSGCM,
@@ -200,6 +200,7 @@ JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_PauseEmulati
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_StopEmulation(JNIEnv *env, jobject obj)
{
PowerPC::Stop();
updateMainFrameEvent.Set(); // Kick the waiting event
}
JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_onTouchEvent(JNIEnv *env, jobject obj, jint Action, jfloat X, jfloat Y)
{
@@ -11,6 +11,7 @@
#include "FileUtil.h"
#include "MathUtil.h"
#include "NandPaths.h"
#include "FileUtil.h"
#include <algorithm>
static Common::replace_v replacements;
@@ -21,18 +22,63 @@ const u8 MD5_BLANKER[0x10] = {0x0E, 0x65, 0x37, 0x81, 0x99, 0xBE, 0x45, 0x17,
0xAB, 0x06, 0xEC, 0x22, 0x45, 0x1A, 0x57, 0x93};
const u32 NG_id = 0x0403AC68;
bool CWiiSaveCrypted::ImportWiiSave(const char* FileName)
{
CWiiSaveCrypted saveFile(FileName);
return saveFile.b_valid;
}
bool CWiiSaveCrypted::ExportWiiSave(u64 TitleID)
{
CWiiSaveCrypted exportSave("", TitleID);
return exportSave.b_valid;
}
void CWiiSaveCrypted::ExportAllSaves()
{
std::string titleFolder = File::GetUserPath(D_WIIUSER_IDX) + "title";
std::vector<u64> titles;
u32 pathMask = 0x00010000;
for (int i = 0; i < 8; ++i)
{
File::FSTEntry FST_Temp;
std::string folder = StringFromFormat("%s/%08x/", titleFolder.c_str(), pathMask | i);
File::ScanDirectoryTree(folder, FST_Temp);
for (u32 j = 0; j < FST_Temp.children.size(); j++)
{
if (FST_Temp.children[j].isDirectory)
{
u32 gameid;
if (AsciiToHex(FST_Temp.children[j].virtualName.c_str(), gameid))
{
std::string bannerPath = StringFromFormat("%s%08x/data/banner.bin", folder.c_str(), gameid);
if (File::Exists(bannerPath))
{
u64 titleID = (((u64)pathMask | i) << 32) | gameid;
titles.push_back(titleID);
}
}
}
}
}
SuccessAlertT("Found %llx save files", titles.size());
for (u32 i = 0; i < titles.size(); ++i)
{
CWiiSaveCrypted* exportSave = new CWiiSaveCrypted("", titles[i]);
delete exportSave;
}
}
CWiiSaveCrypted::CWiiSaveCrypted(const char* FileName, u64 TitleID)
: m_TitleID(TitleID)
{
Common::ReadReplacements(replacements);
strcpy(pathData_bin, FileName);
encryptedSavePath = std::string(FileName);
memcpy(SD_IV, "\x21\x67\x12\xE6\xAA\x1F\x68\x9F\x95\xC5\xA2\x23\x24\xDC\x6A\x98", 0x10);
if (!TitleID) // Import
{
AES_set_decrypt_key(SDKey, 128, &m_AES_KEY);
do
{
b_valid = true;
ReadHDR();
ReadBKHDR();
@@ -41,13 +87,11 @@ CWiiSaveCrypted::CWiiSaveCrypted(const char* FileName, u64 TitleID)
if (b_valid)
{
SuccessAlertT("Successfully imported save files");
b_tryAgain = false;
}
else
{
b_tryAgain = AskYesNoT("Import failed, try again?");
PanicAlertT("Import failed");
}
} while(b_tryAgain);
}
else
{
@@ -55,33 +99,29 @@ CWiiSaveCrypted::CWiiSaveCrypted(const char* FileName, u64 TitleID)
if (getPaths(true))
{
do
b_valid = true;
WriteHDR();
WriteBKHDR();
ExportWiiSaveFiles();
do_sig();
if (b_valid)
{
b_valid = true;
WriteHDR();
WriteBKHDR();
ExportWiiSaveFiles();
do_sig();
if (b_valid)
{
SuccessAlertT("Successfully exported file to %s", pathData_bin);
b_tryAgain = false;
}
else
{
b_tryAgain = AskYesNoT("Export failed, try again?");
}
} while(b_tryAgain);
SuccessAlertT("Successfully exported file to %s", encryptedSavePath.c_str());
}
else
{
PanicAlertT("Export failed");
}
}
}
}
void CWiiSaveCrypted::ReadHDR()
{
File::IOFile fpData_bin(pathData_bin, "rb");
File::IOFile fpData_bin(encryptedSavePath, "rb");
if (!fpData_bin)
{
PanicAlertT("Cannot open %s", pathData_bin);
PanicAlertT("Cannot open %s", encryptedSavePath.c_str());
b_valid = false;
return;
}
@@ -94,16 +134,19 @@ void CWiiSaveCrypted::ReadHDR()
fpData_bin.Close();
AES_cbc_encrypt((const u8*)&_encryptedHeader, (u8*)&_header, HEADER_SZ, &m_AES_KEY, SD_IV, AES_DECRYPT);
_bannerSize = Common::swap32(_header.hdr.BannerSize);
if ((_bannerSize < FULL_BNR_MIN) || (_bannerSize > FULL_BNR_MAX) ||
(((_bannerSize - BNR_SZ) % ICON_SZ) != 0))
u32 bannerSize = Common::swap32(_header.hdr.BannerSize);
if ((bannerSize < FULL_BNR_MIN) || (bannerSize > FULL_BNR_MAX) ||
(((bannerSize - BNR_SZ) % ICON_SZ) != 0))
{
PanicAlertT("Not a Wii save or read failure for file header size %x", _bannerSize);
PanicAlertT("Not a Wii save or read failure for file header size %x", bannerSize);
b_valid = false;
return;
}
m_TitleID = Common::swap64(_header.hdr.SaveGameTitle);
u8 md5_file[16],
md5_calc[16];
memcpy(md5_file, _header.hdr.Md5, 0x10);
memcpy(_header.hdr.Md5, MD5_BLANKER, 0x10);
md5((u8*)&_header, HEADER_SZ, md5_calc);
@@ -118,11 +161,12 @@ void CWiiSaveCrypted::ReadHDR()
b_valid = false;
return;
}
std::string BannerFilePath = WiiTitlePath + "banner.bin";
if (!File::Exists(BannerFilePath) || AskYesNoT("%s already exists, overwrite?", BannerFilePath.c_str()))
{
INFO_LOG(CONSOLE, "Creating file %s", BannerFilePath.c_str());
File::IOFile fpBanner_bin(BannerFilePath, "wb");
fpBanner_bin.WriteBytes(_header.BNR, _bannerSize);
fpBanner_bin.WriteBytes(_header.BNR, bannerSize);
}
}
@@ -131,12 +175,13 @@ void CWiiSaveCrypted::WriteHDR()
if (!b_valid) return;
memset(&_header, 0, HEADER_SZ);
std::string BannerFilePath = WiiTitlePath + "banner.bin";
u32 bannerSize = File::GetSize(BannerFilePath);
_header.hdr.BannerSize = Common::swap32(bannerSize);
_header.hdr.SaveGameTitle = Common::swap64(m_TitleID);
memcpy(_header.hdr.Md5, MD5_BLANKER, 0x10);
_header.hdr.Permissions = 0x35;
_header.hdr.Permissions = 0x3C;
File::IOFile fpBanner_bin(BannerFilePath, "rb");
if (!fpBanner_bin.ReadBytes(_header.BNR, bannerSize))
@@ -145,16 +190,19 @@ void CWiiSaveCrypted::WriteHDR()
b_valid = false;
return;
}
// remove nocopy flag
_header.BNR[7] &= ~1;
u8 md5_calc[16];
md5((u8*)&_header, HEADER_SZ, md5_calc);
memcpy(_header.hdr.Md5, md5_calc, 0x10);
AES_cbc_encrypt((const unsigned char *)&_header, (u8*)&_encryptedHeader, HEADER_SZ, &m_AES_KEY, SD_IV, AES_ENCRYPT);
File::IOFile fpData_bin(pathData_bin, "wb");
File::IOFile fpData_bin(encryptedSavePath, "wb");
if (!fpData_bin.WriteBytes(&_encryptedHeader, HEADER_SZ))
{
PanicAlertT("Failed to write header for %s", pathData_bin);
PanicAlertT("Failed to write header for %s", encryptedSavePath.c_str());
b_valid = false;
}
}
@@ -165,10 +213,10 @@ void CWiiSaveCrypted::ReadBKHDR()
{
if (!b_valid) return;
File::IOFile fpData_bin(pathData_bin, "rb");
File::IOFile fpData_bin(encryptedSavePath, "rb");
if (!fpData_bin)
{
PanicAlertT("Cannot open %s", pathData_bin);
PanicAlertT("Cannot open %s", encryptedSavePath.c_str());
b_valid = false;
return;
}
@@ -215,7 +263,7 @@ void CWiiSaveCrypted::WriteBKHDR()
bkhdr.totalSize = Common::swap32(_sizeOfFiles + FULL_CERT_SZ);
bkhdr.SaveGameTitle = Common::swap64(m_TitleID);
File::IOFile fpData_bin(pathData_bin, "ab");
File::IOFile fpData_bin(encryptedSavePath, "ab");
if (!fpData_bin.WriteBytes(&bkhdr, BK_SZ))
{
PanicAlertT("Failed to write bkhdr");
@@ -227,10 +275,10 @@ void CWiiSaveCrypted::ImportWiiSaveFiles()
{
if (!b_valid) return;
File::IOFile fpData_bin(pathData_bin, "rb");
File::IOFile fpData_bin(encryptedSavePath, "rb");
if (!fpData_bin)
{
PanicAlertT("Cannot open %s", pathData_bin);
PanicAlertT("Cannot open %s", encryptedSavePath.c_str());
b_valid = false;
return;
}
@@ -244,11 +292,11 @@ void CWiiSaveCrypted::ImportWiiSaveFiles()
{
memset(&_tmpFileHDR, 0, FILE_HDR_SZ);
memset(IV, 0, 0x10);
_fileSize = 0;
u32 _fileSize = 0;
if (!fpData_bin.ReadBytes(&_tmpFileHDR, FILE_HDR_SZ))
{
PanicAlertT("Failed to write header for file %d", i);
PanicAlertT("Failed to read header for file %d", i);
b_valid = false;
}
@@ -267,14 +315,15 @@ void CWiiSaveCrypted::ImportWiiSaveFiles()
}
std::string fullFilePath = WiiTitlePath + fileName;
File::CreateFullPath(fullFilePath);
File::CreateFullPath(fullFilePath);
if (_tmpFileHDR.type == 1)
{
_fileSize = Common::swap32(_tmpFileHDR.size);
u32 RoundedFileSize = ROUND_UP(_fileSize, BLOCK_SZ);
_encryptedData = new u8[RoundedFileSize];
_data = new u8[RoundedFileSize];
if (!fpData_bin.ReadBytes(_encryptedData, RoundedFileSize))
std::vector<u8> _data,_encryptedData;
_data.reserve(RoundedFileSize);
_encryptedData.reserve(RoundedFileSize);
if (!fpData_bin.ReadBytes(&_encryptedData[0], RoundedFileSize))
{
PanicAlertT("Failed to read data from file %d", i);
b_valid = false;
@@ -283,17 +332,15 @@ void CWiiSaveCrypted::ImportWiiSaveFiles()
memcpy(IV, _tmpFileHDR.IV, 0x10);
AES_cbc_encrypt((const unsigned char *)_encryptedData, _data, RoundedFileSize, &m_AES_KEY, IV, AES_DECRYPT);
delete []_encryptedData;
AES_cbc_encrypt((const unsigned char *)&_encryptedData[0], &_data[0], RoundedFileSize, &m_AES_KEY, IV, AES_DECRYPT);
if (!File::Exists(fullFilePath) || AskYesNoT("%s already exists, overwrite?", fullFilePath.c_str()))
{
INFO_LOG(CONSOLE, "Creating file %s", fullFilePath.c_str());
File::IOFile fpRawSaveFile(fullFilePath, "wb");
fpRawSaveFile.WriteBytes(_data, _fileSize);
fpRawSaveFile.WriteBytes(&_data[0], _fileSize);
}
delete []_data;
}
}
}
@@ -303,25 +350,29 @@ void CWiiSaveCrypted::ExportWiiSaveFiles()
{
if (!b_valid) return;
u8 *__ENCdata,
*__data;
for(u32 i = 0; i < _numberOfFiles; i++)
{
FileHDR tmpFileHDR;
std::string __name, __ext;
memset(&tmpFileHDR, 0, FILE_HDR_SZ);
_fileSize = File::GetSize(FilesList[i]);
_roundedfileSize = ROUND_UP(_fileSize, BLOCK_SZ);
u32 _fileSize = 0;
if (File::IsDirectory(FilesList[i]))
{
tmpFileHDR.type = 2;
}
else
{
_fileSize = File::GetSize(FilesList[i]);
tmpFileHDR.type = 1;
}
u32 _roundedfileSize = ROUND_UP(_fileSize, BLOCK_SZ);
tmpFileHDR.magic = Common::swap32(FILE_HDR_MAGIC);
tmpFileHDR.size = Common::swap32(_fileSize);
tmpFileHDR.Permissions = 0x35;
tmpFileHDR.type = File::IsDirectory(FilesList[i]) ? 2 : 1;
tmpFileHDR.Permissions = 0x3c;
SplitPath(FilesList[i], NULL, &__name, &__ext);
__name += __ext;
__name = FilesList[i].substr(WiiTitlePath.length()+1);
for (Common::replace_v::const_iterator iter = replacements.begin(); iter != replacements.end(); ++iter)
@@ -341,7 +392,7 @@ void CWiiSaveCrypted::ExportWiiSaveFiles()
strncpy((char *)tmpFileHDR.name, __name.c_str(), __name.length());
{
File::IOFile fpData_bin(pathData_bin, "ab");
File::IOFile fpData_bin(encryptedSavePath, "ab");
fpData_bin.WriteBytes(&tmpFileHDR, FILE_HDR_SZ);
}
@@ -359,22 +410,23 @@ void CWiiSaveCrypted::ExportWiiSaveFiles()
PanicAlertT("%s failed to open", FilesList[i].c_str());
b_valid = false;
}
__data = new u8[_roundedfileSize];
__ENCdata = new u8[_roundedfileSize];
memset(__data, 0, _roundedfileSize);
if (!fpRawSaveFile.ReadBytes(__data, _fileSize))
std::vector<u8> _data,_encryptedData;
_data.reserve(_roundedfileSize);
_encryptedData.reserve(_roundedfileSize);
memset(&_data[0], 0, _roundedfileSize);
if (!fpRawSaveFile.ReadBytes(&_data[0], _fileSize))
{
PanicAlertT("Failed to read data from file: %s", FilesList[i].c_str());
b_valid = false;
}
AES_cbc_encrypt((const u8*)__data, __ENCdata, _roundedfileSize, &m_AES_KEY, tmpFileHDR.IV, AES_ENCRYPT);
AES_cbc_encrypt((const u8*)&_data[0], &_encryptedData[0], _roundedfileSize, &m_AES_KEY, tmpFileHDR.IV, AES_ENCRYPT);
File::IOFile fpData_bin(pathData_bin, "ab");
fpData_bin.WriteBytes(__ENCdata, _roundedfileSize);
File::IOFile fpData_bin(encryptedSavePath, "ab");
if (!fpData_bin.WriteBytes(&_encryptedData[0], _roundedfileSize))
PanicAlertT("Failed to write data to file: %s", encryptedSavePath.c_str());
delete [] __data;
delete [] __ENCdata;
}
}
@@ -424,7 +476,7 @@ void CWiiSaveCrypted::do_sig()
data_size = Common::swap32(bkhdr.sizeOfFiles) + 0x80;
File::IOFile fpData_bin(pathData_bin, "rb");
File::IOFile fpData_bin(encryptedSavePath, "rb");
if (!fpData_bin)
{
b_valid = false;
@@ -443,7 +495,7 @@ void CWiiSaveCrypted::do_sig()
sha1(hash, 20, hash);
delete []data;
fpData_bin.Open(pathData_bin, "ab");
fpData_bin.Open(encryptedSavePath, "ab");
if (!fpData_bin)
{
b_valid = false;
@@ -478,7 +530,6 @@ bool CWiiSaveCrypted::getPaths(bool forExport)
if (m_TitleID)
{
WiiTitlePath = Common::GetTitleDataPath(m_TitleID);
BannerFilePath = WiiTitlePath + "banner.bin";
}
if (forExport)
@@ -495,16 +546,16 @@ bool CWiiSaveCrypted::getPaths(bool forExport)
return false;
}
if(!File::Exists(BannerFilePath))
if(!File::Exists(WiiTitlePath + "banner.bin"))
{
b_valid = false;
PanicAlertT("No banner file found for title %s", GameID);
return false;
}
if (strlen(pathData_bin) == 0)
strcpy(pathData_bin, "."); // If no path was passed, use current dir
sprintf(pathData_bin, "%s/private/wii/title/%s/data.bin", pathData_bin, GameID);
File::CreateFullPath(pathData_bin);
if (encryptedSavePath.length() == 0)
encryptedSavePath = "."; // If no path was passed, use current dir
encryptedSavePath += StringFromFormat("/private/wii/title/%s/data.bin", GameID);
File::CreateFullPath(encryptedSavePath);
}
else
{
@@ -535,15 +586,20 @@ void CWiiSaveCrypted::ScanForFiles(std::string savDir, std::vector<std::string>&
if (strncmp(FST_Temp.children.at(j).virtualName.c_str(), "banner.bin", 10) != 0)
{
(*_numFiles)++;
*_sizeFiles += FILE_HDR_SZ + ROUND_UP(FST_Temp.children.at(j).size, BLOCK_SZ);
*_sizeFiles += FILE_HDR_SZ;
if (FST_Temp.children.at(j).isDirectory)
{
if ((FST_Temp.children.at(j).virtualName == "nocopy") || FST_Temp.children.at(j).virtualName == "nomove")
{
PanicAlert("This save will likely require homebrew tools to copy to a real wii");
}
Directories.push_back(FST_Temp.children.at(j).physicalName);
}
else
{
FileList.push_back(FST_Temp.children.at(j).physicalName);
*_sizeFiles += ROUND_UP(FST_Temp.children.at(j).size, BLOCK_SZ);
}
}
}
@@ -16,6 +16,11 @@
class CWiiSaveCrypted
{
public:
bool static ImportWiiSave(const char* FileName);
bool static ExportWiiSave(u64 TitleID);
void static ExportAllSaves();
private:
CWiiSaveCrypted(const char* FileName, u64 TitleID = 0);
~CWiiSaveCrypted();
void ReadHDR();
@@ -30,33 +35,26 @@ public:
bool getPaths(bool forExport = false);
void ScanForFiles(std::string savDir, std::vector<std::string>&FilesList, u32 *_numFiles, u32 *_sizeFiles);
private:
AES_KEY m_AES_KEY;
u8 SD_IV[0x10];
std::vector<std::string> FilesList;
char pathData_bin[2048];
std::string encryptedSavePath;
std::string BannerFilePath,
WiiTitlePath;
u8 IV[0x10],
*_encryptedData,
*_data,
md5_file[16],
md5_calc[16];
u32 _bannerSize,
u8 IV[0x10];
u32 //_bannerSize,
_numberOfFiles,
_sizeOfFiles,
_totalSize,
_fileSize,
_roundedfileSize;
_totalSize;
u64 m_TitleID;
bool b_valid,
b_tryAgain;
bool b_valid;
enum
{
-4
View File
@@ -107,7 +107,6 @@ NetPlaySetupDiag::NetPlaySetupDiag(wxWindow* const parent, const CGameListCtrl*
" - DSP Emulator Engine Must be the same on all computers!\n"
" - DSP on Dedicated Thread [OFF]\n"
" - Framelimit NOT set to [Audio]\n"
" - Manually set the exact number of controllers to be used to [Standard Controller]\n"
"\n"
"All players should use the same Dolphin version and settings.\n"
"All memory cards must be identical between players or disabled.\n"
@@ -405,9 +404,6 @@ void NetPlayDiag::GetNetSettings(NetSettings &settings)
settings.m_DSPHLE = instance.m_LocalCoreStartupParameter.bDSPHLE;
settings.m_DSPEnableJIT = instance.m_EnableJIT;
settings.m_WriteToMemcard = m_memcard_write->GetValue();
for (unsigned int i = 0; i < 4; ++i)
settings.m_Controllers[i] = SConfig::GetInstance().m_SIDevice[i];
}
std::string NetPlayDiag::FindGame()