Merge branch 'master' of https://code.google.com/p/dolphin-emu into android-core-control
This commit is contained in:
@@ -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>
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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"
|
||||
|
||||
@@ -853,7 +853,7 @@ IOFile::IOFile(IOFile&& other)
|
||||
|
||||
IOFile& IOFile::operator=(IOFile&& other)
|
||||
{
|
||||
IOFile((IOFile&&)other).Swap(*this);
|
||||
Swap(other);
|
||||
return *this;
|
||||
}
|
||||
|
||||
|
||||
@@ -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>
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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()
|
||||
{
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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();
|
||||
}
|
||||
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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"));
|
||||
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -324,6 +324,7 @@ private:
|
||||
|
||||
void OnMemcard(wxCommandEvent& event); // Misc
|
||||
void OnImportSave(wxCommandEvent& event);
|
||||
void OnExportAllSaves(wxCommandEvent& event);
|
||||
|
||||
void OnNetPlay(wxCommandEvent& event);
|
||||
|
||||
|
||||
@@ -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());
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
{
|
||||
|
||||
@@ -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()
|
||||
|
||||
Reference in New Issue
Block a user