diff --git a/CMakeLists.txt b/CMakeLists.txt index b7123f23d7..d350fdeb2d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -524,11 +524,16 @@ else() set(LZO lzo2) endif() -if(ANDROID) +if(NOT ${CMAKE_SYSTEM_NAME} MATCHES "Darwin" AND NOT ANDROID) + check_lib(PNG png png.h QUIET) +endif() +if (PNG_FOUND) + message("Using shared libpng") +else() message("Using static libpng from Externals") add_subdirectory(Externals/libpng) include_directories(Externals/libpng) - set(PNG libpng) + set(PNG png) endif() if(OPENAL_FOUND) diff --git a/Externals/wxWidgets3/CMakeLists.txt b/Externals/wxWidgets3/CMakeLists.txt index 1ce7a73418..6629d0865e 100644 --- a/Externals/wxWidgets3/CMakeLists.txt +++ b/Externals/wxWidgets3/CMakeLists.txt @@ -868,8 +868,6 @@ if(${CMAKE_SYSTEM_NAME} MATCHES "Darwin") ${SRCS_GENERICOSX} ${SRCS_OSX} ${SRCS_UNIX}) - include_directories(../libpng) - add_subdirectory(../libpng ../libpng) set(LIBS png iconv diff --git a/Source/Android/res/layout/gamelist_folderbrowser_list.xml b/Source/Android/res/layout/gamelist_folderbrowser_list_item.xml similarity index 100% rename from Source/Android/res/layout/gamelist_folderbrowser_list.xml rename to Source/Android/res/layout/gamelist_folderbrowser_list_item.xml diff --git a/Source/Android/res/menu/emuwindow_overlay.xml b/Source/Android/res/menu/emuwindow_overlay.xml index d1c480c284..dc875203e8 100644 --- a/Source/Android/res/menu/emuwindow_overlay.xml +++ b/Source/Android/res/menu/emuwindow_overlay.xml @@ -1,7 +1,11 @@ + ビルドのバージョン サポートのOpenGL ES 3 + サポートのNEON 現在のディレクトリ: %1$s @@ -25,10 +26,15 @@ 設定 について + + デバイスの互換性の警告 + この電話は、NEON拡張をサポートしていません。 おそらくDolphinを実行することはできません。\nあなたはとにかくそれを実行してみますか? + クリックされたファイル: %1$s + スクリーンショットを撮る ステートセーブ ステートロード 終了 diff --git a/Source/Android/res/values/strings.xml b/Source/Android/res/values/strings.xml index 983f9e6ace..ca7157fd44 100644 --- a/Source/Android/res/values/strings.xml +++ b/Source/Android/res/values/strings.xml @@ -11,6 +11,7 @@ Build Revision Supports OpenGL ES 3 + Supports NEON Current Dir: %1$s @@ -25,10 +26,15 @@ Settings About + + Device Compatibility Warning + Your phone doesn\'t support NEON which makes it incapable of running Dolphin Mobile?\nDo you want to try anyway? + File clicked: %1$s + Take Screenshot Save State Load State Exit diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java index 8b29e607d7..defefcc0d4 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java @@ -6,7 +6,6 @@ package org.dolphinemu.dolphinemu; -import android.app.Activity; import android.app.ListFragment; import android.content.Context; import android.os.Bundle; @@ -27,35 +26,24 @@ import org.dolphinemu.dolphinemu.settings.VideoSettingsFragment; */ public final class AboutFragment extends ListFragment { - private static Activity m_activity; - @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.gamelist_listview, container, false); - ListView mMainList = (ListView) rootView.findViewById(R.id.gamelist); + ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); - String yes = getString(R.string.yes); - String no = getString(R.string.no); + final String yes = getString(R.string.yes); + final String no = getString(R.string.no); List Input = new ArrayList(); Input.add(new AboutFragmentItem(getString(R.string.build_revision), NativeLibrary.GetVersionString())); Input.add(new AboutFragmentItem(getString(R.string.supports_gles3), VideoSettingsFragment.SupportsGLES3() ? yes : no)); + Input.add(new AboutFragmentItem(getString(R.string.supports_neon), NativeLibrary.SupportsNEON() ? yes : no)); - AboutFragmentAdapter adapter = new AboutFragmentAdapter(m_activity, R.layout.about_layout, Input); - mMainList.setAdapter(adapter); - mMainList.setEnabled(false); // Makes the list view non-clickable. + AboutFragmentAdapter adapter = new AboutFragmentAdapter(getActivity(), R.layout.about_layout, Input); + rootView.setAdapter(adapter); + rootView.setEnabled(false); // Makes the list view non-clickable. - return mMainList; - } - - @Override - public void onAttach(Activity activity) - { - super.onAttach(activity); - - // Cache the activity instance. - m_activity = activity; + return rootView; } // Represents an item in the AboutFragment. @@ -106,18 +94,17 @@ public final class AboutFragment extends ListFragment @Override public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - if (v == null) + if (convertView == null) { - LayoutInflater vi = (LayoutInflater) ctx.getSystemService(Context.LAYOUT_INFLATER_SERVICE); - v = vi.inflate(id, parent, false); + LayoutInflater vi = LayoutInflater.from(ctx); + convertView = vi.inflate(id, parent, false); } final AboutFragmentItem item = items.get(position); if (item != null) { - TextView title = (TextView) v.findViewById(R.id.AboutItemTitle); - TextView subtitle = (TextView) v.findViewById(R.id.AboutItemSubTitle); + TextView title = (TextView) convertView.findViewById(R.id.AboutItemTitle); + TextView subtitle = (TextView) convertView.findViewById(R.id.AboutItemSubTitle); if (title != null) title.setText(item.getTitle()); @@ -126,7 +113,7 @@ public final class AboutFragment extends ListFragment subtitle.setText(item.getSubTitle()); } - return v; + return convertView; } } } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java b/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java index b06669f8f7..bdbe53dfcb 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/DolphinEmulator.java @@ -86,4 +86,9 @@ public final class DolphinEmulator extends Activity UserPreferences.LoadIniToPrefs(this); } } + protected void onRestart() + { + super.onRestart(); + finish(); // If we are ever returning to this activity then we are exiting. + } } \ No newline at end of file diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java index 80fcf64ff6..4662ca4372 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/NativeLibrary.java @@ -104,6 +104,19 @@ public final class NativeLibrary */ public static native String GetVersionString(); + /** + * Returns if the phone supports NEON or not + * + * @return true if it supports NEON, false otherwise. + */ + public static native boolean SupportsNEON(); + + /** + * Saves a screen capture of the game + * + */ + public static native void SaveScreenShot(); + /** * Saves a game state to the slot number. * diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java index 912fc021c5..926b971398 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java @@ -68,12 +68,14 @@ public final class EmulationActivity extends Activity // Due to a bug in Adreno, it renders the screen rotated 90 degrees when using OpenGL // Flip the width and height when on Adreno to work around this. + // This bug is fixed in Qualcomm driver v53 // Mali isn't affected by this bug. SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(this); if (prefs.getString("gpuPref", "Software Rendering").equals("OGL") && VideoSettingsFragment.SupportsGLES3() && VideoSettingsFragment.m_GLVendor != null - && VideoSettingsFragment.m_GLVendor.equals("Qualcomm")) + && VideoSettingsFragment.m_GLVendor.equals("Qualcomm") + && VideoSettingsFragment.m_QualcommVersion < 53.0f) NativeLibrary.SetDimensions((int)screenHeight, (int)screenWidth); else NativeLibrary.SetDimensions((int)screenWidth, (int)screenHeight); @@ -173,6 +175,11 @@ public final class EmulationActivity extends Activity { switch(item.getItemId()) { + // Screenshot capturing + case R.id.takeScreenshot: + NativeLibrary.SaveScreenShot(); + return true; + // Save state slots case R.id.saveSlot1: NativeLibrary.SaveState(0); diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java index 1697311fe3..8aa561376a 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java @@ -6,7 +6,6 @@ package org.dolphinemu.dolphinemu.folderbrowser; -import android.app.Activity; import android.app.ListFragment; import android.os.Bundle; import android.os.Environment; @@ -37,16 +36,18 @@ import org.dolphinemu.dolphinemu.gamelist.GameListActivity; */ public final class FolderBrowser extends ListFragment { - private Activity m_activity; private FolderBrowserAdapter adapter; - private ListView mFolderBrowserList; - private ListView rootView; private static File currentDir = null; // Populates the FolderView with the given currDir's contents. private void Fill(File currDir) { - m_activity.setTitle(String.format(getString(R.string.current_dir), currDir.getName())); + // Clear the adapter of previous items. + adapter.clear(); + + // Set the activity title to the current directory the FolderBrowser is in. + getActivity().setTitle(String.format(getString(R.string.current_dir), currDir.getName())); + File[] dirs = currDir.listFiles(); List dir = new ArrayList(); List fls = new ArrayList(); @@ -96,9 +97,9 @@ public final class FolderBrowser extends ListFragment if (!currDir.getPath().equalsIgnoreCase("/")) dir.add(0, new FolderBrowserItem("..", getString(R.string.parent_directory), currDir.getParent())); - adapter = new FolderBrowserAdapter(m_activity, R.layout.gamelist_folderbrowser_list, dir); - mFolderBrowserList = (ListView) rootView.findViewById(R.id.gamelist); - mFolderBrowserList.setAdapter(adapter); + // Add the items to the adapter and notify the adapter users of its new contents. + adapter.addAll(dir); + adapter.notifyDataSetChanged(); } @Override @@ -122,22 +123,14 @@ public final class FolderBrowser extends ListFragment if(currentDir == null) currentDir = new File(Environment.getExternalStorageDirectory().getPath()); - rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); + ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); + adapter = new FolderBrowserAdapter(getActivity(), R.layout.gamelist_folderbrowser_list_item); + rootView.setAdapter(adapter); Fill(currentDir); - return mFolderBrowserList; + return rootView; } - @Override - public void onAttach(Activity activity) - { - super.onAttach(activity); - - // Cache the activity instance. - m_activity = activity; - } - - private void FolderSelected() { String Directories = NativeLibrary.GetConfig("Dolphin.ini", "General", "GCMPathes", "0"); @@ -168,6 +161,6 @@ public final class FolderBrowser extends ListFragment NativeLibrary.SetConfig("Dolphin.ini", "General", "GCMPath" + Integer.toString(intDirectories), currentDir.getPath()); } - ((GameListActivity)m_activity).SwitchPage(0); + ((GameListActivity)getActivity()).SwitchPage(0); } } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java index 8d96a8232c..f97799e6e4 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowserAdapter.java @@ -6,15 +6,12 @@ package org.dolphinemu.dolphinemu.folderbrowser; -import java.util.List; - import android.content.Context; import android.view.LayoutInflater; import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; -import android.widget.ListView; import android.widget.TextView; import org.dolphinemu.dolphinemu.R; @@ -27,79 +24,89 @@ import org.dolphinemu.dolphinemu.R; */ public final class FolderBrowserAdapter extends ArrayAdapter { + // ViewHolder which is used to hold onto + // items within a listview. This is done + // so that findViewById is not needed to + // be excessively called over and over. + private static final class ViewHolder + { + TextView title; + TextView subtitle; + ImageView icon; + } + private final Context context; private final int id; - private final List items; + private ViewHolder viewHolder; /** * Constructor * * @param context The current {@link Context}. * @param resourceId The resource ID for a layout file containing a layout to use when instantiating views. - * @param objects The objects to represent in the {@link ListView}. */ - public FolderBrowserAdapter(Context context, int resourceId, List objects) + public FolderBrowserAdapter(Context context, int resourceId) { - super(context, resourceId, objects); + super(context, resourceId); this.context = context; this.id = resourceId; - this.items = objects; - } - - @Override - public FolderBrowserItem getItem(int i) - { - return items.get(i); } @Override public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - if (v == null) + if (convertView == null) { LayoutInflater vi = LayoutInflater.from(context); - v = vi.inflate(id, parent, false); + convertView = vi.inflate(id, parent, false); + + // Initialize the ViewHolder and store it. + viewHolder = new ViewHolder(); + viewHolder.title = (TextView) convertView.findViewById(R.id.ListItemTitle); + viewHolder.subtitle = (TextView) convertView.findViewById(R.id.ListItemSubTitle); + viewHolder.icon = (ImageView) convertView.findViewById(R.id.ListItemIcon); + convertView.setTag(viewHolder); + } + else // Can recover the holder. + { + viewHolder = (ViewHolder) convertView.getTag(); } - final FolderBrowserItem item = items.get(position); + final FolderBrowserItem item = getItem(position); if (item != null) { - ImageView icon = (ImageView) v.findViewById(R.id.ListItemIcon); - TextView title = (TextView) v.findViewById(R.id.ListItemTitle); - TextView subtitle = (TextView) v.findViewById(R.id.ListItemSubTitle); - - if(title != null) + if (viewHolder.title != null) { - title.setText(item.getName()); + viewHolder.title.setText(item.getName()); } - if(subtitle != null) + if (viewHolder.subtitle != null) { // Remove the subtitle for all folders, except for the parent directory folder. if (item.isDirectory() && !item.getSubtitle().equals(context.getString(R.string.parent_directory))) { - subtitle.setVisibility(View.GONE); + viewHolder.subtitle.setVisibility(View.GONE); } else { - subtitle.setText(item.getSubtitle()); + viewHolder.subtitle.setVisibility(View.VISIBLE); + viewHolder.subtitle.setText(item.getSubtitle()); } } - if (icon != null) + if (viewHolder.icon != null) { if (item.isDirectory()) { - icon.setImageResource(R.drawable.ic_menu_folder); + viewHolder.icon.setImageResource(R.drawable.ic_menu_folder); } else { - icon.setImageResource(R.drawable.ic_menu_file); + viewHolder.icon.setImageResource(R.drawable.ic_menu_file); } } } - return v; + return convertView; } } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java index 96f1783310..940632a8ea 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java @@ -9,20 +9,21 @@ package org.dolphinemu.dolphinemu.gamelist; import android.app.Activity; import android.app.AlertDialog; import android.app.Fragment; -import android.app.FragmentManager; +import android.app.FragmentTransaction; import android.content.DialogInterface; import android.content.Intent; import android.content.res.Configuration; +import android.os.Build; import android.os.Bundle; import android.support.v4.app.ActionBarDrawerToggle; import android.support.v4.widget.DrawerLayout; -import android.view.*; +import android.view.Menu; +import android.view.MenuInflater; +import android.view.MenuItem; +import android.view.View; import android.widget.AdapterView; import android.widget.ListView; -import java.util.ArrayList; -import java.util.List; - import org.dolphinemu.dolphinemu.AboutFragment; import org.dolphinemu.dolphinemu.NativeLibrary; import org.dolphinemu.dolphinemu.R; @@ -31,6 +32,9 @@ import org.dolphinemu.dolphinemu.settings.PrefsActivity; import org.dolphinemu.dolphinemu.sidemenu.SideMenuAdapter; import org.dolphinemu.dolphinemu.sidemenu.SideMenuItem; +import java.util.ArrayList; +import java.util.List; + /** * The activity that implements all of the functions * for the game list. @@ -39,7 +43,6 @@ public final class GameListActivity extends Activity implements GameListFragment.OnGameListZeroListener { private int mCurFragmentNum = 0; - private Fragment mCurFragment; private ActionBarDrawerToggle mDrawerToggle; private DrawerLayout mDrawerLayout; @@ -100,10 +103,36 @@ public final class GameListActivity extends Activity }; mDrawerLayout.setDrawerListener(mDrawerToggle); - // Display the game list fragment. - mCurFragment = new GameListFragment(); - FragmentManager fragmentManager = getFragmentManager(); - fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit(); + // Display the game list fragment on activity creation, + // but only if no previous states have been saved. + if (savedInstanceState == null) + { + final GameListFragment gameList = new GameListFragment(); + FragmentTransaction ft = getFragmentManager().beginTransaction(); + ft.replace(R.id.content_frame, gameList); + ft.commit(); + } + + + // Create an alert telling them that their phone sucks + if (Build.CPU_ABI.contains("arm") && !NativeLibrary.SupportsNEON()) + { + AlertDialog.Builder builder = new AlertDialog.Builder(this); + builder.setTitle(R.string.device_compat_warning); + builder.setMessage(R.string.device_compat_warning_msg); + builder.setPositiveButton(R.string.yes, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) { + // Do Nothing. Just create the Yes button + } + }); + builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { + public void onClick(DialogInterface dialog, int which) + { + finish(); + } + }); + builder.show(); + } } /** @@ -127,9 +156,10 @@ public final class GameListActivity extends Activity setTitle(R.string.app_name); mCurFragmentNum = 0; - mCurFragment = new GameListFragment(); - FragmentManager fragmentManager = getFragmentManager(); - fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit(); + final GameListFragment gameList = new GameListFragment(); + FragmentTransaction ft = getFragmentManager().beginTransaction(); + ft.replace(R.id.content_frame, gameList); + ft.commit(); invalidateOptionsMenu(); } break; @@ -137,9 +167,11 @@ public final class GameListActivity extends Activity case 1: // Folder Browser { mCurFragmentNum = 1; - mCurFragment = new FolderBrowser(); - FragmentManager fragmentManager = getFragmentManager(); - fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit(); + final FolderBrowser folderBrowser = new FolderBrowser(); + FragmentTransaction ft = getFragmentManager().beginTransaction(); + ft.replace(R.id.content_frame, folderBrowser); + ft.addToBackStack(null); + ft.commit(); invalidateOptionsMenu(); } break; @@ -154,9 +186,11 @@ public final class GameListActivity extends Activity case 3: // About { mCurFragmentNum = 3; - mCurFragment = new AboutFragment(); - FragmentManager fragmentManager = getFragmentManager(); - fragmentManager.beginTransaction().replace(R.id.content_frame, mCurFragment).commit(); + final AboutFragment aboutFragment = new AboutFragment(); + FragmentTransaction ft = getFragmentManager().beginTransaction(); + ft.replace(R.id.content_frame, aboutFragment); + ft.addToBackStack(null); + ft.commit(); invalidateOptionsMenu(); } break; @@ -243,7 +277,7 @@ public final class GameListActivity extends Activity NativeLibrary.SetConfig("Dolphin.ini", "General", "GCMPathes", "0"); // Now finally, clear the game list. - ((GameListFragment) mCurFragment).clearGameList(); + ((GameListFragment) getFragmentManager().findFragmentById(R.id.content_frame)).clearGameList(); } }); builder.setNegativeButton(R.string.no, new DialogInterface.OnClickListener() { @@ -258,7 +292,23 @@ public final class GameListActivity extends Activity return super.onOptionsItemSelected(item); } - + + @Override + public void onSaveInstanceState(Bundle outState) + { + super.onSaveInstanceState(outState); + + outState.putInt("currentFragmentNum", mCurFragmentNum); + } + + @Override + public void onRestoreInstanceState(Bundle savedInstanceState) + { + super.onRestoreInstanceState(savedInstanceState); + + mCurFragmentNum = savedInstanceState.getInt("currentFragmentNum"); + } + @Override public void onBackPressed() { diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java index d0b3642ffe..d4dedd29aa 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListAdapter.java @@ -12,11 +12,8 @@ import android.view.View; import android.view.ViewGroup; import android.widget.ArrayAdapter; import android.widget.ImageView; -import android.widget.ListView; import android.widget.TextView; -import java.util.List; - import org.dolphinemu.dolphinemu.R; /** @@ -28,46 +25,36 @@ public final class GameListAdapter extends ArrayAdapter { private final Context context; private final int id; - private final Listitems; /** * Constructor * * @param context The current {@link Context}. * @param resourceId The resource ID for a layout file containing a layout to use when instantiating views. - * @param objects The objects to represent in the {@link ListView}. */ - public GameListAdapter(Context context, int resourceId, List objects) + public GameListAdapter(Context context, int resourceId) { - super(context, resourceId, objects); + super(context, resourceId); this.context = context; this.id = resourceId; - this.items = objects; - } - - @Override - public GameListItem getItem(int i) - { - return items.get(i); } @Override public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - if (v == null) + if (convertView == null) { LayoutInflater vi = LayoutInflater.from(context); - v = vi.inflate(id, parent, false); + convertView = vi.inflate(id, parent, false); } - final GameListItem item = items.get(position); + final GameListItem item = getItem(position); if (item != null) { - TextView title = (TextView) v.findViewById(R.id.ListItemTitle); - TextView subtitle = (TextView) v.findViewById(R.id.ListItemSubTitle); - ImageView icon = (ImageView) v.findViewById(R.id.ListItemIcon); + TextView title = (TextView) convertView.findViewById(R.id.ListItemTitle); + TextView subtitle = (TextView) convertView.findViewById(R.id.ListItemSubTitle); + ImageView icon = (ImageView) convertView.findViewById(R.id.ListItemIcon); if (title != null) title.setText(item.getName()); @@ -83,7 +70,7 @@ public final class GameListAdapter extends ArrayAdapter } } - return v; + return convertView; } } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java index 41eb271b99..9dedf914dc 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListFragment.java @@ -35,7 +35,6 @@ import org.dolphinemu.dolphinemu.emulation.EmulationActivity; public final class GameListFragment extends ListFragment { private GameListAdapter mGameAdapter; - private static GameListActivity mMe; private OnGameListZeroListener mCallback; /** @@ -84,7 +83,7 @@ public final class GameListFragment extends ListFragment if (!entry.isHidden() && !entry.isDirectory()) { if (exts.contains(entryName.toLowerCase().substring(entryName.lastIndexOf('.')))) - fls.add(new GameListItem(mMe, entryName, String.format(getString(R.string.file_size), entry.length()), entry.getAbsolutePath())); + fls.add(new GameListItem(getActivity(), entryName, String.format(getString(R.string.file_size), entry.length()), entry.getAbsolutePath())); } } } @@ -94,8 +93,9 @@ public final class GameListFragment extends ListFragment } Collections.sort(fls); - mGameAdapter = new GameListAdapter(mMe, R.layout.gamelist_folderbrowser_list, fls); - setListAdapter(mGameAdapter); + // Add all the items to the adapter + mGameAdapter.addAll(fls); + mGameAdapter.notifyDataSetChanged(); if (fls.isEmpty()) { @@ -106,12 +106,13 @@ public final class GameListFragment extends ListFragment @Override public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) { - View rootView = inflater.inflate(R.layout.gamelist_listview, container, false); - ListView mMainList = (ListView) rootView.findViewById(R.id.gamelist); + ListView rootView = (ListView) inflater.inflate(R.layout.gamelist_listview, container, false); + mGameAdapter = new GameListAdapter(getActivity(), R.layout.gamelist_folderbrowser_list_item); + rootView.setAdapter(mGameAdapter); Fill(); - return mMainList; + return rootView; } @Override @@ -120,12 +121,12 @@ public final class GameListFragment extends ListFragment GameListItem item = mGameAdapter.getItem(position); // Show a toast indicating which game was clicked. - Toast.makeText(mMe, String.format(getString(R.string.file_clicked), item.getPath()), Toast.LENGTH_SHORT).show(); + Toast.makeText(getActivity(), String.format(getString(R.string.file_clicked), item.getPath()), Toast.LENGTH_SHORT).show(); // Start the emulation activity and send the path of the clicked ROM to it. - Intent intent = new Intent(mMe, EmulationActivity.class); + Intent intent = new Intent(getActivity(), EmulationActivity.class); intent.putExtra("SelectedGame", item.getPath()); - mMe.startActivity(intent); + startActivity(intent); } @Override @@ -138,7 +139,6 @@ public final class GameListFragment extends ListFragment try { mCallback = (OnGameListZeroListener) activity; - mMe = (GameListActivity) activity; } catch (ClassCastException e) { diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/settings/VideoSettingsFragment.java b/Source/Android/src/org/dolphinemu/dolphinemu/settings/VideoSettingsFragment.java index 8cf7cf0cf4..b88ea07afe 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/settings/VideoSettingsFragment.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/settings/VideoSettingsFragment.java @@ -28,6 +28,7 @@ public final class VideoSettingsFragment extends PreferenceFragment public static String m_GLVendor; public static String m_GLRenderer; public static String m_GLExtensions; + public static float m_QualcommVersion; private Activity m_activity; /** @@ -165,7 +166,6 @@ public final class VideoSettingsFragment extends PreferenceFragment { int mVStart = m_GLVersion.indexOf("V@") + 2; int mVEnd = 0; - float mVersion; for (int a = mVStart; a < m_GLVersion.length(); ++a) { @@ -176,9 +176,9 @@ public final class VideoSettingsFragment extends PreferenceFragment } } - mVersion = Float.parseFloat(m_GLVersion.substring(mVStart, mVEnd)); + m_QualcommVersion = Float.parseFloat(m_GLVersion.substring(mVStart, mVEnd)); - if (mVersion >= 14.0f) + if (m_QualcommVersion >= 14.0f) mSupportsGLES3 = true; } } diff --git a/Source/Android/src/org/dolphinemu/dolphinemu/sidemenu/SideMenuAdapter.java b/Source/Android/src/org/dolphinemu/dolphinemu/sidemenu/SideMenuAdapter.java index 6ea97e3f66..60fd8b56f3 100644 --- a/Source/Android/src/org/dolphinemu/dolphinemu/sidemenu/SideMenuAdapter.java +++ b/Source/Android/src/org/dolphinemu/dolphinemu/sidemenu/SideMenuAdapter.java @@ -54,23 +54,22 @@ public final class SideMenuAdapter extends ArrayAdapter @Override public View getView(int position, View convertView, ViewGroup parent) { - View v = convertView; - if (v == null) + if (convertView == null) { LayoutInflater vi = LayoutInflater.from(context); - v = vi.inflate(id, null); + convertView = vi.inflate(id, null); } final SideMenuItem item = items.get(position); if (item != null) { - TextView title = (TextView) v.findViewById(R.id.SideMenuTitle); + TextView title = (TextView) convertView.findViewById(R.id.SideMenuTitle); if (title != null) title.setText(item.getName()); } - return v; + return convertView; } } diff --git a/Source/Core/AudioCommon/Src/AudioCommon.cpp b/Source/Core/AudioCommon/Src/AudioCommon.cpp index acb9f95067..c8c37ea891 100644 --- a/Source/Core/AudioCommon/Src/AudioCommon.cpp +++ b/Source/Core/AudioCommon/Src/AudioCommon.cpp @@ -23,7 +23,7 @@ SoundStream *soundStream = nullptr; namespace AudioCommon { - SoundStream *InitSoundStream(CMixer *mixer) + SoundStream *InitSoundStream(CMixer *mixer, void *hWnd) { // TODO: possible memleak with mixer @@ -33,7 +33,7 @@ namespace AudioCommon else if (backend == BACKEND_NULLSOUND && NullSound::isValid()) soundStream = new NullSound(mixer); else if (backend == BACKEND_DIRECTSOUND && DSound::isValid()) - soundStream = new DSound(mixer); + soundStream = new DSound(mixer, hWnd); else if (backend == BACKEND_XAUDIO2) { if (XAudio2::isValid()) diff --git a/Source/Core/AudioCommon/Src/AudioCommon.h b/Source/Core/AudioCommon/Src/AudioCommon.h index 8ff5ff38e1..9c49293a48 100644 --- a/Source/Core/AudioCommon/Src/AudioCommon.h +++ b/Source/Core/AudioCommon/Src/AudioCommon.h @@ -40,7 +40,7 @@ union UDSPControl namespace AudioCommon { - SoundStream *InitSoundStream(CMixer *mixer); + SoundStream *InitSoundStream(CMixer *mixer, void *hWnd); void ShutdownSoundStream(); std::vector GetSoundBackends(); bool UseJIT(); diff --git a/Source/Core/AudioCommon/Src/DSoundStream.h b/Source/Core/AudioCommon/Src/DSoundStream.h index 8778c7e863..a872e79181 100644 --- a/Source/Core/AudioCommon/Src/DSoundStream.h +++ b/Source/Core/AudioCommon/Src/DSoundStream.h @@ -48,7 +48,7 @@ class DSound : public SoundStream bool WriteDataToBuffer(DWORD dwOffset, char* soundData, DWORD dwSoundBytes); public: - DSound(CMixer *mixer, void *_hWnd = NULL) + DSound(CMixer *mixer, void *_hWnd) : SoundStream(mixer) , bufferSize(0) , currentPos(0) @@ -71,7 +71,7 @@ public: #else public: - DSound(CMixer *mixer) + DSound(CMixer *mixer, void *_hWnd) : SoundStream(mixer) {} #endif diff --git a/Source/Core/Common/Src/ArmEmitter.cpp b/Source/Core/Common/Src/ArmEmitter.cpp index cb9544dce3..6178d2c58c 100644 --- a/Source/Core/Common/Src/ArmEmitter.cpp +++ b/Source/Core/Common/Src/ArmEmitter.cpp @@ -938,13 +938,13 @@ u32 EncodeVm(ARMReg Vm) // Double/single, Neon extern const VFPEnc VFPOps[16][2] = { - {{0xE0, 0xA0}, {0x20, 0xD1}}, // 0: VMLA + {{0xE0, 0xA0}, { -1, -1}}, // 0: VMLA {{0xE1, 0xA4}, { -1, -1}}, // 1: VNMLA - {{0xE0, 0xA4}, {0x22, 0xD1}}, // 2: VMLS + {{0xE0, 0xA4}, { -1, -1}}, // 2: VMLS {{0xE1, 0xA0}, { -1, -1}}, // 3: VNMLS - {{0xE3, 0xA0}, {0x20, 0xD0}}, // 4: VADD - {{0xE3, 0xA4}, {0x22, 0xD0}}, // 5: VSUB - {{0xE2, 0xA0}, {0x30, 0xD1}}, // 6: VMUL + {{0xE3, 0xA0}, { -1, -1}}, // 4: VADD + {{0xE3, 0xA4}, { -1, -1}}, // 5: VSUB + {{0xE2, 0xA0}, { -1, -1}}, // 6: VMUL {{0xE2, 0xA4}, { -1, -1}}, // 7: VNMUL {{0xEB, 0xAC}, { -1 /* 0x3B */, -1 /* 0x70 */}}, // 8: VABS(Vn(0x0) used for encoding) {{0xE8, 0xA0}, { -1, -1}}, // 9: VDIV @@ -1237,7 +1237,7 @@ void ARMXEmitter::VCVT(ARMReg Dest, ARMReg Source, int flags) } } -void NEONXEmitter::VABA(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VABA(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1248,7 +1248,7 @@ void NEONXEmitter::VABA(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) | (encodedSize(Size) << 20) | EncodeVd(Vd) | (0x71 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VABAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VABAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, Vn >= D0 && Vn < Q0, "Pass invalid register to " __FUNCTION__); @@ -1260,7 +1260,7 @@ void NEONXEmitter::VABAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) | (encodedSize(Size) << 20) | EncodeVd(Vd) | (0x50 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VABD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VABD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1273,7 +1273,7 @@ void NEONXEmitter::VABD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) | (encodedSize(Size) << 20) | EncodeVd(Vd) | (0x70 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VABDL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VABDL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, Vn >= D0 && Vn < Q0, "Pass invalid register to " __FUNCTION__); @@ -1285,7 +1285,7 @@ void NEONXEmitter::VABDL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) | (encodedSize(Size) << 20) | EncodeVd(Vd) | (0x70 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VABS(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VABS(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1327,7 +1327,7 @@ void NEONXEmitter::VACLT(ARMReg Vd, ARMReg Vn, ARMReg Vm) VACGT(Vd, Vn, Vm); } -void NEONXEmitter::VADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1341,7 +1341,7 @@ void NEONXEmitter::VADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) | (0x8 << 8) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VADDHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VADDHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd < Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, Vn >= Q0, "Pass invalid register to " __FUNCTION__); @@ -1353,7 +1353,7 @@ void NEONXEmitter::VADDHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) | EncodeVd(Vd) | (0x80 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VADDL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VADDL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, Vn >= D0 && Vn < Q0, "Pass invalid register to " __FUNCTION__); @@ -1364,7 +1364,7 @@ void NEONXEmitter::VADDL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) \ | EncodeVd(Vd) | EncodeVm(Vm)); } -void NEONXEmitter::VADDW(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VADDW(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, Vn >= Q0, "Pass invalid register to " __FUNCTION__); @@ -1420,7 +1420,7 @@ void NEONXEmitter::VBSL(ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF3 << 24) | (1 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCEQ(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VCEQ(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1433,7 +1433,7 @@ void NEONXEmitter::VCEQ(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) | (0x81 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCEQ(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VCEQ(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1443,7 +1443,7 @@ void NEONXEmitter::VCEQ(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF2 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 16) \ | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (0x10 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCGE(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VCGE(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1455,7 +1455,7 @@ void NEONXEmitter::VCGE(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) \ | (0x31 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCGE(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VCGE(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1464,7 +1464,7 @@ void NEONXEmitter::VCGE(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 16) \ | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (0x8 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCGT(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VCGT(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1476,7 +1476,7 @@ void NEONXEmitter::VCGT(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) \ | (0x30 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCGT(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VCGT(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1485,11 +1485,11 @@ void NEONXEmitter::VCGT(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) | (1 << 16) \ | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCLE(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VCLE(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { VCGE(Size, Vd, Vm, Vn); } -void NEONXEmitter::VCLE(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VCLE(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1498,7 +1498,7 @@ void NEONXEmitter::VCLE(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) | (1 << 16) \ | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (3 << 7) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCLS(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VCLS(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1508,11 +1508,11 @@ void NEONXEmitter::VCLS(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) \ | EncodeVd(Vd) | (1 << 10) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCLT(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VCLT(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { VCGT(Size, Vd, Vm, Vn); } -void NEONXEmitter::VCLT(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VCLT(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1521,7 +1521,7 @@ void NEONXEmitter::VCLT(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) | (1 << 16) \ | EncodeVd(Vd) | ((Size & F_32 ? 1 : 0) << 10) | (0x20 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCLZ(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VCLZ(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1530,7 +1530,7 @@ void NEONXEmitter::VCLZ(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) \ | EncodeVd(Vd) | (0x48 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VCNT(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VCNT(u32 Size, ARMReg Vd, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1540,7 +1540,7 @@ void NEONXEmitter::VCNT(NEONElementType Size, ARMReg Vd, ARMReg Vm) Write32((0xF3 << 24) | (0xD << 20) | (encodedSize(Size) << 18) \ | EncodeVd(Vd) | (0x90 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VDUP(NEONElementType Size, ARMReg Vd, ARMReg Vm, u8 index) +void NEONXEmitter::VDUP(u32 Size, ARMReg Vd, ARMReg Vm, u8 index) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1562,7 +1562,7 @@ void NEONXEmitter::VDUP(NEONElementType Size, ARMReg Vd, ARMReg Vm, u8 index) Write32((0xF3 << 24) | (0xD << 20) | (sizeEncoded << 16) | (indexEncoded << 16) \ | EncodeVd(Vd) | (0xC0 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VDUP(NEONElementType Size, ARMReg Vd, ARMReg Rt) +void NEONXEmitter::VDUP(u32 Size, ARMReg Vd, ARMReg Rt) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, Rt < D0, "Pass invalid register to " __FUNCTION__); @@ -1616,7 +1616,7 @@ void NEONXEmitter::VFMS(ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | (0xC1 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VHADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VHADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1627,7 +1627,7 @@ void NEONXEmitter::VHADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 23) | (encodedSize(Size) << 20) \ | EncodeVn(Vn) | EncodeVd(Vd) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VHSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VHSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1638,7 +1638,7 @@ void NEONXEmitter::VHSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 23) | (encodedSize(Size) << 20) \ | EncodeVn(Vn) | EncodeVd(Vd) | (1 << 9) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VMAX(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VMAX(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1651,7 +1651,7 @@ void NEONXEmitter::VMAX(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 23) | (encodedSize(Size) << 20) \ | EncodeVn(Vn) | EncodeVd(Vd) | (0x60 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VMIN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VMIN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1664,7 +1664,7 @@ void NEONXEmitter::VMIN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 23) | (encodedSize(Size) << 20) \ | EncodeVn(Vn) | EncodeVd(Vd) | (0x61 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VMLA(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VMLA(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1676,7 +1676,7 @@ void NEONXEmitter::VMLA(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) else Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x90 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VMLS(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VMLS(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); @@ -1688,7 +1688,7 @@ void NEONXEmitter::VMLS(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) else Write32((0xF2 << 24) | (1 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x90 << 4) | (register_quad << 6) | EncodeVm(Vm)); } -void NEONXEmitter::VMLAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VMLAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, Vn >= Q0, "Pass invalid register to " __FUNCTION__); @@ -1699,7 +1699,7 @@ void NEONXEmitter::VMLAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (encodedSize(Size) << 20) \ | EncodeVn(Vn) | EncodeVd(Vd) | (0x80 << 4) | EncodeVm(Vm)); } -void NEONXEmitter::VMLSL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VMLSL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); _dbg_assert_msg_(DYNA_REC, Vn >= Q0, "Pass invalid register to " __FUNCTION__); @@ -1710,23 +1710,404 @@ void NEONXEmitter::VMLSL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) Write32((0xF2 << 24) | ((Size & I_UNSIGNED ? 1 : 0) << 24) | (encodedSize(Size) << 20) \ | EncodeVn(Vn) | EncodeVd(Vd) | (0xA0 << 4) | EncodeVm(Vm)); } - -void NEONXEmitter::VSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +void NEONXEmitter::VMUL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) { - _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to VSUB(integer)"); - _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use VSUB(integer) when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); - // Gets encoded as a double register + bool register_quad = Vd >= Q0; + + if (Size & F_32) + Write32((0xF3 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xD1 << 4) | (register_quad << 6) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | ((Size & I_POLYNOMIAL) ? (1 << 24) : 0) | (encodedSize(Size) << 20) | \ + EncodeVn(Vn) | EncodeVd(Vd) | (0x91 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VMULL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xC0 << 4) | ((Size & I_POLYNOMIAL) ? 1 << 9 : 0) | EncodeVm(Vm)); +} +void NEONXEmitter::VNEG(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 16) | \ + EncodeVd(Vd) | ((Size & F_32) ? 1 << 10 : 0) | (0xE << 6) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VORN(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (3 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VORR(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (2 << 20) | EncodeVn(Vn) | EncodeVd(Vd) | (0x11 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VPADAL(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | EncodeVd(Vd) | \ + (0x60 << 4) | ((Size & I_UNSIGNED) ? 1 << 7 : 0) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VPADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + if (Size & F_32) + Write32((0xF3 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xD0 << 4) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xB1 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VPADDL(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | EncodeVd(Vd) | \ + (0x20 << 4) | (Size & I_UNSIGNED ? 1 << 7 : 0) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VPMAX(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + if (Size & F_32) + Write32((0xF3 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xF0 << 4) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xA0 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VPMIN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + if (Size & F_32) + Write32((0xF3 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | (0xF0 << 4) | EncodeVm(Vm)); + else + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xA1 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VQABS(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | EncodeVd(Vd) | \ + (0x70 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VQADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x1 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VQDMLAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x90 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VQDMLSL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xB0 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VQDMULH(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xB0 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VQDMULL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF2 << 24) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xD0 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VQNEG(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | EncodeVd(Vd) | \ + (0x78 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VQRDMULH(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF3 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xB0 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VQRSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x51 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VQSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x41 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VQSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x21 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VRADDHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF3 << 24) | (1 << 23) | ((encodedSize(Size) - 1) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x40 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VRECPE(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (0xB << 16) | EncodeVd(Vd) | \ + (0x40 << 4) | (Size & F_32 ? 1 << 8 : 0) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VRECPS(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | EncodeVn(Vn) | EncodeVd(Vd) | (0xF1 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VRHADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x10 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VRSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x50 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VRSQRTE(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; Vd = SubBase(Vd); - Vn = SubBase(Vn); Vm = SubBase(Vm); - Write32((0xF3 << 24) | ((Vd & 0x10) << 18) | (encodedSize(Size) << 20) | ((Vn & 0xF) << 16) \ - | ((Vd & 0xF) << 12) | (0x8 << 8) | ((Vn & 0x10) << 3) | (1 << 6) \ - | ((Vm & 0x10) << 1) | (Vm & 0xF)); + Write32((0xF3 << 24) | (0xB << 20) | ((Vd & 0x10) << 18) | (0xB << 16) + | ((Vd & 0xF) << 12) | (9 << 7) | (Size & F_32 ? (1 << 8) : 0) | (register_quad << 6) + | ((Vm & 0x10) << 1) | (Vm & 0xF)); } +void NEONXEmitter::VRSQRTS(ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); -void NEONXEmitter::VLD1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align, ARMReg Rm) + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xF1 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VRSUBHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + Write32((0xF3 << 24) | (1 << 23) | ((encodedSize(Size) - 1) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x60 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= D0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + _dbg_assert_msg_(DYNA_REC, !(Size & F_32), __FUNCTION__ " doesn't support float"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x40 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + if (Size & F_32) + Write32((0xF2 << 24) | (1 << 21) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0xD0 << 4) | (register_quad << 6) | EncodeVm(Vm)); + else + Write32((0xF3 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x80 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VSUBHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + Write32((0xF2 << 24) | (1 << 23) | ((encodedSize(Size) - 1) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x60 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VSUBL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x20 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VSUBW(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + Write32((0xF2 << 24) | (Size & I_UNSIGNED ? 1 << 24 : 0) | (1 << 23) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x30 << 4) | EncodeVm(Vm)); +} +void NEONXEmitter::VSWP(ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (1 << 17) | EncodeVd(Vd) | \ + (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VTRN(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 17) | EncodeVd(Vd) | \ + (1 << 7) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VTST(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF2 << 24) | (encodedSize(Size) << 20) | EncodeVn(Vn) | EncodeVd(Vd) | \ + (0x81 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VUZP(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 17) | EncodeVd(Vd) | \ + (0x10 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VZIP(u32 Size, ARMReg Vd, ARMReg Vm) +{ + _dbg_assert_msg_(DYNA_REC, Vd >= Q0, "Pass invalid register to " __FUNCTION__); + _dbg_assert_msg_(DYNA_REC, cpu_info.bNEON, "Can't use " __FUNCTION__ " when CPU doesn't support it"); + + bool register_quad = Vd >= Q0; + + Write32((0xF3 << 24) | (0xB << 20) | (encodedSize(Size) << 18) | (1 << 17) | EncodeVd(Vd) | \ + (0x18 << 4) | (register_quad << 6) | EncodeVm(Vm)); +} +void NEONXEmitter::VLD1(u32 Size, ARMReg Vd, ARMReg Rn, NEONAlignment align, ARMReg Rm) { u32 spacing = 0x7; // Only support loading to 1 reg // Gets encoded as a double register @@ -1736,8 +2117,7 @@ void NEONXEmitter::VLD1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignmen | ((Vd & 0xF) << 12) | (spacing << 8) | (encodedSize(Size) << 6) | (align << 4) | Rm); } - -void NEONXEmitter::VLD2(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align, ARMReg Rm) +void NEONXEmitter::VLD2(u32 Size, ARMReg Vd, ARMReg Rn, NEONAlignment align, ARMReg Rm) { u32 spacing = 0x8; // Single spaced registers // Gets encoded as a double register @@ -1747,8 +2127,7 @@ void NEONXEmitter::VLD2(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignmen | ((Vd & 0xF) << 12) | (spacing << 8) | (encodedSize(Size) << 6) | (align << 4) | Rm); } - -void NEONXEmitter::VST1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align, ARMReg Rm) +void NEONXEmitter::VST1(u32 Size, ARMReg Vd, ARMReg Rn, NEONAlignment align, ARMReg Rm) { u32 spacing = 0x7; // Single spaced registers // Gets encoded as a double register @@ -1759,8 +2138,7 @@ void NEONXEmitter::VST1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignmen | (align << 4) | Rm); } - -void NEONXEmitter::VREVX(u32 size, NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VREVX(u32 size, u32 Size, ARMReg Vd, ARMReg Vm) { bool register_quad = Vd >= Q0; Vd = SubBase(Vd); @@ -1771,44 +2149,19 @@ void NEONXEmitter::VREVX(u32 size, NEONElementType Size, ARMReg Vd, ARMReg Vm) | (register_quad << 6) | ((Vm & 0x10) << 1) | (Vm & 0xF)); } -void NEONXEmitter::VREV64(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VREV64(u32 Size, ARMReg Vd, ARMReg Vm) { VREVX(0, Size, Vd, Vm); } -void NEONXEmitter::VREV32(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VREV32(u32 Size, ARMReg Vd, ARMReg Vm) { VREVX(1, Size, Vd, Vm); } -void NEONXEmitter::VREV16(NEONElementType Size, ARMReg Vd, ARMReg Vm) +void NEONXEmitter::VREV16(u32 Size, ARMReg Vd, ARMReg Vm) { VREVX(2, Size, Vd, Vm); } - -void NEONXEmitter::VRSQRTE(NEONElementType Size, ARMReg Vd, ARMReg Vm) -{ - bool register_quad = Vd >= Q0; - Vd = SubBase(Vd); - Vm = SubBase(Vm); - - Write32((0xF3 << 24) | (0xB << 20) | ((Vd & 0x10) << 18) | (0xB << 16) - | ((Vd & 0xF) << 12) | (9 << 7) | (Size & F_32 ? (1 << 8) : 0) | (register_quad << 6) - | ((Vm & 0x10) << 1) | (Vm & 0xF)); -} - -void NEONXEmitter::VORR(ARMReg Vd, ARMReg Vn, ARMReg Vm) -{ - bool register_quad = Vd >= Q0; - Vd = SubBase(Vd); - Vn = SubBase(Vn); - Vm = SubBase(Vm); - - Write32((0xF2 << 24) | (0x1 << 21) | ((Vd & 0x10) << 18) | ((Vn & 0xF) << 16) - | ((Vd & 0xF) << 12) | (1 << 8) | ((Vn & 0x10) << 3) - | (register_quad << 6) | ((Vm & 0x10) << 1) | (1 << 4) | (Vm & 0xF)); -} - - } diff --git a/Source/Core/Common/Src/ArmEmitter.h b/Source/Core/Common/Src/ArmEmitter.h index cdfddd8d7e..99024f3b6f 100644 --- a/Source/Core/Common/Src/ArmEmitter.h +++ b/Source/Core/Common/Src/ArmEmitter.h @@ -338,6 +338,15 @@ struct LiteralPool }; typedef const u8* JumpTarget; +// XXX: Stop polluting the global namespace +const u32 I_8 = (1 << 0); +const u32 I_16 = (1 << 1); +const u32 I_32 = (1 << 2); +const u32 I_64 = (1 << 3); +const u32 I_SIGNED = (1 << 4); +const u32 I_UNSIGNED = (1 << 5); +const u32 F_32 = (1 << 6); +const u32 I_POLYNOMIAL = (1 << 7); // Only used in VMUL/VMULL u32 EncodeVd(ARMReg Vd); u32 EncodeVn(ARMReg Vn); @@ -572,17 +581,6 @@ public: }; // class ARMXEmitter -enum NEONElementType -{ - I_8 = (1 << 0), - I_16 = (1 << 1), - I_32 = (1 << 2), - I_64 = (1 << 3), - I_SIGNED = (1 << 4), - I_UNSIGNED = (1 << 5), - F_32 = (1 << 6) -}; - enum NEONAlignment { ALIGN_NONE = 0, @@ -613,71 +611,105 @@ private: return 0; } - void VREVX(u32 size, NEONElementType Size, ARMReg Vd, ARMReg Vm); + void VREVX(u32 size, u32 Size, ARMReg Vd, ARMReg Vm); -public: +public: NEONXEmitter(ARMXEmitter *emit) : _emit(emit) {} - void VABA(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VABAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VABD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VABDL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VABS(NEONElementType Size, ARMReg Vd, ARMReg Vm); + void VABA(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VABAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VABD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VABDL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VABS(u32 Size, ARMReg Vd, ARMReg Vm); void VACGE(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VACGT(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VACLE(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VACLT(ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VADDHN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VADDL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VADDW(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VADDHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VADDL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VADDW(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); void VAND(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VBIC(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VBIF(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VBIT(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VBSL(ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VCEQ(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VCEQ(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VCGE(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VCGE(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VCGT(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VCGT(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VCLE(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VCLE(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VCLS(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VCLT(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VCLT(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VCLZ(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VCNT(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VDUP(NEONElementType Size, ARMReg Vd, ARMReg Vm, u8 index); - void VDUP(NEONElementType Size, ARMReg Vd, ARMReg Rt); + void VCEQ(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VCEQ(u32 Size, ARMReg Vd, ARMReg Vm); + void VCGE(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VCGE(u32 Size, ARMReg Vd, ARMReg Vm); + void VCGT(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VCGT(u32 Size, ARMReg Vd, ARMReg Vm); + void VCLE(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VCLE(u32 Size, ARMReg Vd, ARMReg Vm); + void VCLS(u32 Size, ARMReg Vd, ARMReg Vm); + void VCLT(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VCLT(u32 Size, ARMReg Vd, ARMReg Vm); + void VCLZ(u32 Size, ARMReg Vd, ARMReg Vm); + void VCNT(u32 Size, ARMReg Vd, ARMReg Vm); + void VDUP(u32 Size, ARMReg Vd, ARMReg Vm, u8 index); + void VDUP(u32 Size, ARMReg Vd, ARMReg Rt); void VEOR(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VEXT(ARMReg Vd, ARMReg Vn, ARMReg Vm, u8 index); void VFMA(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VFMS(ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VHADD(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VHSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VMAX(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VMIN(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VMLA(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VMLS(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VMLAL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VMLSL(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VSUB(NEONElementType Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); - void VREV64(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VREV32(NEONElementType Size, ARMReg Vd, ARMReg Vm); - void VREV16(NEONElementType Size, ARMReg Vd, ARMReg Vm); - - void VRSQRTE(NEONElementType Size, ARMReg Vd, ARMReg Vm); - + void VHADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VHSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMAX(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMIN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMLA(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMLS(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMLAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMLSL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMUL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VMULL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VNEG(u32 Size, ARMReg Vd, ARMReg Vm); + void VORN(ARMReg Vd, ARMReg Vn, ARMReg Vm); void VORR(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VPADAL(u32 Size, ARMReg Vd, ARMReg Vm); + void VPADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VPADDL(u32 Size, ARMReg Vd, ARMReg Vm); + void VPMAX(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VPMIN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQABS(u32 Size, ARMReg Vd, ARMReg Vm); + void VQADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMLAL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMLSL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMULH(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQDMULL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQNEG(u32 Size, ARMReg Vd, ARMReg Vm); + void VQRDMULH(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQRSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VQSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRADDHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRECPE(u32 Size, ARMReg Vd, ARMReg Vm); + void VRECPS(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRHADD(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRSQRTE(u32 Size, ARMReg Vd, ARMReg Vm); + void VRSQRTS(ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VRSUBHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSHL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUB(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUBHN(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUBL(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSUBW(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VSWP(ARMReg Vd, ARMReg Vm); + void VTRN(u32 Size, ARMReg Vd, ARMReg Vm); + void VTST(u32 Size, ARMReg Vd, ARMReg Vn, ARMReg Vm); + void VUZP(u32 Size, ARMReg Vd, ARMReg Vm); + void VZIP(u32 Size, ARMReg Vd, ARMReg Vm); + void VREV64(u32 Size, ARMReg Vd, ARMReg Vm); + void VREV32(u32 Size, ARMReg Vd, ARMReg Vm); + void VREV16(u32 Size, ARMReg Vd, ARMReg Vm); - void VLD1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); - void VLD2(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); + void VLD1(u32 Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); + void VLD2(u32 Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); - void VST1(NEONElementType Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); + void VST1(u32 Size, ARMReg Vd, ARMReg Rn, NEONAlignment align = ALIGN_NONE, ARMReg Rm = _PC); }; // Everything that needs to generate X86 code should inherit from this. diff --git a/Source/Core/Common/Src/CPUDetect.h b/Source/Core/Common/Src/CPUDetect.h index be6ce34985..967be0949b 100644 --- a/Source/Core/Common/Src/CPUDetect.h +++ b/Source/Core/Common/Src/CPUDetect.h @@ -41,7 +41,14 @@ struct CPUInfo bool bLZCNT; bool bSSE4A; bool bAVX; + bool bFMA; bool bAES; + // FXSAVE/FXRSTOR + bool bFXSR; + // This flag indicates that the hardware supports some mode + // in which denormal inputs _and_ outputs are automatically set to (signed) zero. + // TODO: ARM + bool bFlushToZero; bool bLAHFSAHF64; bool bLongMode; diff --git a/Source/Core/Common/Src/ChunkFile.h b/Source/Core/Common/Src/ChunkFile.h index 5192b4332e..d7aeba0558 100644 --- a/Source/Core/Common/Src/ChunkFile.h +++ b/Source/Core/Common/Src/ChunkFile.h @@ -193,10 +193,12 @@ public: void DoPointer(T*& x, T* const base) { // pointers can be more than 2^31 apart, but you're using this function wrong if you need that much range - s32 offset = x - base; + ptrdiff_t offset = x - base; Do(offset); if (mode == MODE_READ) + { x = base + offset; + } } // Let's pretend std::list doesn't exist! diff --git a/Source/Core/Common/Src/CommonFuncs.h b/Source/Core/Common/Src/CommonFuncs.h index bf50a1756f..63bdc04dfb 100644 --- a/Source/Core/Common/Src/CommonFuncs.h +++ b/Source/Core/Common/Src/CommonFuncs.h @@ -31,7 +31,12 @@ struct ArraySizeImpl : public std::extent #define b32(x) (b16(x) | (b16(x) >>16) ) #define ROUND_UP_POW2(x) (b32(x - 1) + 1) -#if defined __GNUC__ && !defined __SSSE3__ && !defined _M_GENERIC +#ifndef __GNUC_PREREQ + #define __GNUC_PREREQ(a, b) 0 +#endif + +#if (defined __GNUC__ && !__GNUC_PREREQ(4,9)) \ + && !defined __SSSE3__ && !defined _M_GENERIC #include static __inline __m128i __attribute__((__always_inline__)) _mm_shuffle_epi8(__m128i a, __m128i mask) diff --git a/Source/Core/Common/Src/FPURoundMode.h b/Source/Core/Common/Src/FPURoundMode.h index fad4d5d6aa..c552ad7ff0 100644 --- a/Source/Core/Common/Src/FPURoundMode.h +++ b/Source/Core/Common/Src/FPURoundMode.h @@ -36,7 +36,7 @@ namespace FPURoundMode void SetPrecisionMode(u32 mode); - void SetSIMDMode(u32 mode); + void SetSIMDMode(u32 roundingMode, u32 nonIEEEMode); /* * There are two different flavors of float to int conversion: diff --git a/Source/Core/Common/Src/GenericFPURoundMode.cpp b/Source/Core/Common/Src/GenericFPURoundMode.cpp index cc878291a1..c8e70a4990 100644 --- a/Source/Core/Common/Src/GenericFPURoundMode.cpp +++ b/Source/Core/Common/Src/GenericFPURoundMode.cpp @@ -26,7 +26,7 @@ namespace FPURoundMode void SetPrecisionMode(u32 mode) { } - void SetSIMDMode(u32 mode) + void SetSIMDMode(u32 mode, u32 nonIEEEMode) { } void SaveSIMDState() diff --git a/Source/Core/Common/Src/MathUtil.h b/Source/Core/Common/Src/MathUtil.h index 31772c3c60..f085c6ed2b 100644 --- a/Source/Core/Common/Src/MathUtil.h +++ b/Source/Core/Common/Src/MathUtil.h @@ -64,10 +64,10 @@ inline float FlushToZero(float f) return x.f; } -inline double FlushToZeroAsFloat(double d) +inline double FlushToZero(double d) { IntDouble x; x.d = d; - if ((x.i & DOUBLE_EXP) < 0x3800000000000000ULL) + if ((x.i & DOUBLE_EXP) == 0) x.i &= DOUBLE_SIGN; // turn into signed zero return x.d; } diff --git a/Source/Core/Common/Src/SDCardUtil.cpp b/Source/Core/Common/Src/SDCardUtil.cpp index cf37ffff3e..5475cf131d 100644 --- a/Source/Core/Common/Src/SDCardUtil.cpp +++ b/Source/Core/Common/Src/SDCardUtil.cpp @@ -36,6 +36,7 @@ #include #include #include +#include #ifndef _WIN32 #include // for unlink() @@ -196,7 +197,7 @@ bool SDCardCreate(u64 disk_size /*in MB*/, const char* filename) disk_size *= 1024 * 1024; if (disk_size < 0x800000 || disk_size > 0x800000000ULL) { - ERROR_LOG(COMMON, "Trying to create SD Card image of size %lliMB is out of range (8MB-32GB)", disk_size/(1024*1024)); + ERROR_LOG(COMMON, "Trying to create SD Card image of size %" PRIu64 "MB is out of range (8MB-32GB)", disk_size/(1024*1024)); return false; } diff --git a/Source/Core/Common/Src/StringUtil.cpp b/Source/Core/Common/Src/StringUtil.cpp index 5243b24260..7ad4ac6ca5 100644 --- a/Source/Core/Common/Src/StringUtil.cpp +++ b/Source/Core/Common/Src/StringUtil.cpp @@ -404,26 +404,30 @@ std::string UriEncode(const std::string & sSrc) std::string UTF16ToUTF8(const std::wstring& input) { - auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), nullptr, 0, nullptr, nullptr); + auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), (int)input.size(), nullptr, 0, nullptr, nullptr); std::string output; output.resize(size); - if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), &output[0], output.size(), nullptr, nullptr)) + if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), (int)input.size(), &output[0], (int)output.size(), nullptr, nullptr)) + { output.clear(); + } return output; } std::wstring CPToUTF16(u32 code_page, const std::string& input) { - auto const size = MultiByteToWideChar(code_page, 0, input.data(), input.size(), nullptr, 0); + auto const size = MultiByteToWideChar(code_page, 0, input.data(), (int)input.size(), nullptr, 0); std::wstring output; output.resize(size); - if (size == 0 || size != MultiByteToWideChar(code_page, 0, input.data(), input.size(), &output[0], output.size())) + if (size == 0 || size != MultiByteToWideChar(code_page, 0, input.data(), (int)input.size(), &output[0], (int)output.size())) + { output.clear(); + } return output; } diff --git a/Source/Core/Common/Src/SysConf.cpp b/Source/Core/Common/Src/SysConf.cpp index e1c3eb8abb..acfb11b0ed 100644 --- a/Source/Core/Common/Src/SysConf.cpp +++ b/Source/Core/Common/Src/SysConf.cpp @@ -5,6 +5,8 @@ #include "FileUtil.h" #include "SysConf.h" +#include + SysConf::SysConf() : m_IsValid(false) { @@ -42,7 +44,7 @@ bool SysConf::LoadFromFile(const char *filename) u64 size = File::GetSize(filename); if (size != SYSCONF_SIZE) { - if (AskYesNoT("Your SYSCONF file is the wrong size.\nIt should be 0x%04x (but is 0x%04llx)\nDo you want to generate a new one?", + if (AskYesNoT("Your SYSCONF file is the wrong size.\nIt should be 0x%04x (but is 0x%04" PRIx64 ")\nDo you want to generate a new one?", SYSCONF_SIZE, size)) { GenerateSysConf(); @@ -151,7 +153,7 @@ unsigned int create_item(SSysConfEntry &item, SysconfType type, const std::strin { item.offset = offset; item.type = type; - item.nameLength = name.length(); + item.nameLength = (u8)(name.length()); strncpy(item.name, name.c_str(), 32); item.dataLength = data_length; item.data = new u8[data_length]; diff --git a/Source/Core/Common/Src/Thread.h b/Source/Core/Common/Src/Thread.h index bfd7ea0308..b2e9572ce5 100644 --- a/Source/Core/Common/Src/Thread.h +++ b/Source/Core/Common/Src/Thread.h @@ -38,7 +38,7 @@ class Event public: Event() : is_set(false) - {}; + {} void Set() { @@ -53,34 +53,20 @@ public: void Wait() { std::unique_lock lk(m_mutex); - m_condvar.wait(lk, IsSet(this)); + m_condvar.wait(lk, [&]{ return is_set; }); is_set = false; } void Reset() { std::unique_lock lk(m_mutex); - // no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration + // no other action required, since wait loops on + // the predicate and any lingering signal will get + // cleared on the first iteration is_set = false; } private: - class IsSet - { - public: - IsSet(const Event* ev) - : m_event(ev) - {} - - bool operator()() - { - return m_event->is_set; - } - - private: - const Event* const m_event; - }; - volatile bool is_set; std::condition_variable m_condvar; std::mutex m_mutex; @@ -110,28 +96,12 @@ public: } else { - m_condvar.wait(lk, IsDoneWating(this)); + m_condvar.wait(lk, [&]{ return (0 == m_waiting); }); return false; } } private: - class IsDoneWating - { - public: - IsDoneWating(const Barrier* bar) - : m_bar(bar) - {} - - bool operator()() - { - return (0 == m_bar->m_waiting); - } - - private: - const Barrier* const m_bar; - }; - std::condition_variable m_condvar; std::mutex m_mutex; const size_t m_count; diff --git a/Source/Core/Common/Src/x64CPUDetect.cpp b/Source/Core/Common/Src/x64CPUDetect.cpp index 07b35cb968..2fa25e8074 100644 --- a/Source/Core/Common/Src/x64CPUDetect.cpp +++ b/Source/Core/Common/Src/x64CPUDetect.cpp @@ -162,6 +162,34 @@ void CPUInfo::Detect() if ((cpu_id[2] >> 20) & 1) bSSE4_2 = true; if ((cpu_id[2] >> 25) & 1) bAES = true; + // To check DAZ support, we first need to check FXSAVE support. + if ((cpu_id[3] >> 24) & 1) + { + // We can use FXSAVE. + bFXSR = true; + + GC_ALIGNED16(u8 fx_state[512]); + memset(fx_state, 0, sizeof(fx_state)); +#ifdef _WIN32 +#ifdef _M_IX86 + _fxsave(fx_state); +#elif defined (_M_X64) + _fxsave64(fx_state); +#endif +#else + __asm__("fxsave %0" : "=m" (fx_state)); +#endif + + // lowest byte of MXCSR_MASK + if ((fx_state[0x1C] >> 6) & 1) + { + // On x86, the FTZ field (supported since SSE1) only flushes denormal _outputs_ to zero, + // now that we checked DAZ support (flushing denormal _inputs_ to zero), + // we can set our generic flag. + bFlushToZero = true; + } + } + // AVX support requires 3 separate checks: // - Is the AVX bit set in CPUID? // - Is the XSAVE bit set in CPUID? @@ -169,7 +197,11 @@ void CPUInfo::Detect() if (((cpu_id[2] >> 28) & 1) && ((cpu_id[2] >> 27) & 1)) { if ((_xgetbv(_XCR_XFEATURE_ENABLED_MASK) & 0x6) == 0x6) + { bAVX = true; + if ((cpu_id[2] >> 12) & 1) + bFMA = true; + } } } if (max_ex_fn >= 0x80000004) { @@ -218,13 +250,19 @@ std::string CPUInfo::Summarize() { std::string sum(cpu_string); if (bSSE) sum += ", SSE"; - if (bSSE2) sum += ", SSE2"; + if (bSSE2) + { + sum += ", SSE2"; + if (!bFlushToZero) + sum += " (but not DAZ!)"; + } if (bSSE3) sum += ", SSE3"; if (bSSSE3) sum += ", SSSE3"; if (bSSE4_1) sum += ", SSE4.1"; if (bSSE4_2) sum += ", SSE4.2"; if (HTT) sum += ", HTT"; if (bAVX) sum += ", AVX"; + if (bFMA) sum += ", FMA"; if (bAES) sum += ", AES"; if (bLongMode) sum += ", 64-bit support"; return sum; diff --git a/Source/Core/Common/Src/x64Emitter.cpp b/Source/Core/Common/Src/x64Emitter.cpp index 8b3002b26a..05540ba4a8 100644 --- a/Source/Core/Common/Src/x64Emitter.cpp +++ b/Source/Core/Common/Src/x64Emitter.cpp @@ -7,6 +7,8 @@ #include "x64ABI.h" #include "CPUDetect.h" +#include + namespace Gen { @@ -154,6 +156,40 @@ void OpArg::WriteRex(XEmitter *emit, int opBits, int bits, int customOp) const #endif } +void OpArg::WriteVex(XEmitter* emit, int size, int packed, Gen::X64Reg regOp1, Gen::X64Reg regOp2) const +{ + int R = !(regOp1 & 8); + int X = !(indexReg & 8); + int B = !(offsetOrBaseReg & 8); + + // not so sure about this one... + int W = 0; + + // aka map_select in AMD manuals + // only support VEX opcode map 1 for now (analog to secondary opcode map) + int mmmmm = 1; + + int vvvv = (regOp2 == X64Reg::INVALID_REG) ? 0xf : (regOp2 ^ 0xf); + int L = size == 256; + int pp = (packed << 1) | (size == 64); + + // do we need any VEX fields that only appear in the three-byte form? + if (X == 1 && B == 1 && W == 0 && mmmmm == 1) + { + u8 RvvvvLpp = (R << 7) | (vvvv << 3) | (L << 1) | pp; + emit->Write8(0xC5); + emit->Write8(RvvvvLpp); + } + else + { + u8 RXBmmmmm = (R << 7) | (X << 6) | (B << 5) | mmmmm; + u8 WvvvvLpp = (W << 7) | (vvvv << 3) | (L << 1) | pp; + emit->Write8(0xC4); + emit->Write8(RXBmmmmm); + emit->Write8(WvvvvLpp); + } +} + void OpArg::WriteRest(XEmitter *emit, int extraBytes, X64Reg _operandReg, bool warn_64bit_offset) const { @@ -176,7 +212,7 @@ void OpArg::WriteRest(XEmitter *emit, int extraBytes, X64Reg _operandReg, _assert_msg_(DYNA_REC, (distance < 0x80000000LL && distance >= -0x80000000LL) || !warn_64bit_offset, - "WriteRest: op out of range (0x%llx uses 0x%llx)", + "WriteRest: op out of range (0x%" PRIx64 " uses 0x%" PRIx64 ")", ripAddr, offset); s32 offs = (s32)distance; emit->Write32((u32)offs); @@ -1141,6 +1177,18 @@ void XEmitter::WriteSSEOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg a arg.WriteRest(this, extrabytes); } +void XEmitter::WriteAVXOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes) +{ + WriteAVXOp(size, sseOp, packed, regOp, X64Reg::INVALID_REG, arg, extrabytes); +} + +void XEmitter::WriteAVXOp(int size, u8 sseOp, bool packed, X64Reg regOp1, X64Reg regOp2, OpArg arg, int extrabytes) +{ + arg.WriteVex(this, size, packed, regOp1, regOp2); + Write8(sseOp); + arg.WriteRest(this, extrabytes, regOp1); +} + void XEmitter::MOVD_xmm(X64Reg dest, const OpArg &arg) {WriteSSEOp(64, 0x6E, true, dest, arg, 0);} void XEmitter::MOVD_xmm(const OpArg &arg, X64Reg src) {WriteSSEOp(64, 0x7E, true, src, arg, 0);} @@ -1444,6 +1492,13 @@ void XEmitter::PMOVMSKB(X64Reg dest, OpArg arg) {WriteSSEOp(64, 0xD7, true, d void XEmitter::PSHUFLW(X64Reg regOp, OpArg arg, u8 shuffle) {WriteSSEOp(64, 0x70, false, regOp, arg, 1); Write8(shuffle);} +// VEX +void XEmitter::VADDSD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(64, sseADD, false, regOp1, regOp2, arg);} +void XEmitter::VSUBSD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(64, sseSUB, false, regOp1, regOp2, arg);} +void XEmitter::VMULSD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(64, sseMUL, false, regOp1, regOp2, arg);} +void XEmitter::VDIVSD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(64, sseDIV, false, regOp1, regOp2, arg);} +void XEmitter::VSQRTSD(X64Reg regOp1, X64Reg regOp2, OpArg arg) {WriteAVXOp(64, sseSQRT, false, regOp1, regOp2, arg);} + // Prefixes void XEmitter::LOCK() { Write8(0xF0); } diff --git a/Source/Core/Common/Src/x64Emitter.h b/Source/Core/Common/Src/x64Emitter.h index 6ce16abcce..87e76ef21a 100644 --- a/Source/Core/Common/Src/x64Emitter.h +++ b/Source/Core/Common/Src/x64Emitter.h @@ -33,6 +33,9 @@ enum X64Reg XMM0=0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7, XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15, + YMM0=0, YMM1, YMM2, YMM3, YMM4, YMM5, YMM6, YMM7, + YMM8, YMM9, YMM10, YMM11, YMM12, YMM13, YMM14, YMM15, + INVALID_REG = 0xFFFFFFFF }; @@ -111,6 +114,7 @@ struct OpArg offset = _offset; } void WriteRex(XEmitter *emit, int opBits, int bits, int customOp = -1) const; + void WriteVex(XEmitter* emit, int size, int packed, Gen::X64Reg regOp1, X64Reg regOp2) const; void WriteRest(XEmitter *emit, int extraBytes=0, X64Reg operandReg=(X64Reg)0xFF, bool warn_64bit_offset = true) const; void WriteSingleByteOp(XEmitter *emit, u8 op, X64Reg operandReg, int bits); // This one is public - must be written to @@ -239,6 +243,8 @@ private: void WriteBitTest(int bits, OpArg &dest, OpArg &index, int ext); void WriteMXCSR(OpArg arg, int ext); void WriteSSEOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes = 0); + void WriteAVXOp(int size, u8 sseOp, bool packed, X64Reg regOp, OpArg arg, int extrabytes = 0); + void WriteAVXOp(int size, u8 sseOp, bool packed, X64Reg regOp1, X64Reg regOp2, OpArg arg, int extrabytes = 0); void WriteNormalOp(XEmitter *emit, int bits, NormalOp op, const OpArg &a1, const OpArg &a2); protected: @@ -616,6 +622,13 @@ public: void PSRAW(X64Reg reg, int shift); void PSRAD(X64Reg reg, int shift); + // AVX + void VADDSD(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VSUBSD(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VMULSD(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VDIVSD(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void VSQRTSD(X64Reg regOp1, X64Reg regOp2, OpArg arg); + void RTDSC(); // Utility functions diff --git a/Source/Core/Common/Src/x64FPURoundMode.cpp b/Source/Core/Common/Src/x64FPURoundMode.cpp index 2c950ade96..f46c6000eb 100644 --- a/Source/Core/Common/Src/x64FPURoundMode.cpp +++ b/Source/Core/Common/Src/x64FPURoundMode.cpp @@ -4,6 +4,7 @@ #include "Common.h" #include "FPURoundMode.h" +#include "CPUDetect.h" #ifndef _WIN32 static const unsigned short FPU_ROUND_NEAR = 0 << 10; @@ -14,8 +15,11 @@ static const unsigned short FPU_ROUND_MASK = 3 << 10; #include #endif -const u32 MASKS = 0x1F80; // mask away the interrupts. +// OR-mask for disabling FPU exceptions (bits 7-12 in the MXCSR register) +const u32 EXCEPTION_MASK = 0x1F80; +// Denormals-Are-Zero (non-IEEE mode: denormal inputs are set to +/- 0) const u32 DAZ = 0x40; +// Flush-To-Zero (non-IEEE mode: denormal outputs are set to +/- 0) const u32 FTZ = 0x8000; namespace FPURoundMode @@ -79,16 +83,28 @@ namespace FPURoundMode //but still - set any useful sse options here #endif } - void SetSIMDMode(u32 mode) + + void SetSIMDMode(u32 roundingMode, u32 nonIEEEMode) { - static const u32 ssetable[4] = + // lookup table for FPSCR.RN-to-MXCSR.RC translation + static const u32 roundingModeLUT[4] = { - (0 << 13) | MASKS, - (3 << 13) | MASKS, - (2 << 13) | MASKS, - (1 << 13) | MASKS, + (0 << 13) | EXCEPTION_MASK, // nearest + (3 << 13) | EXCEPTION_MASK, // -inf + (2 << 13) | EXCEPTION_MASK, // +inf + (1 << 13) | EXCEPTION_MASK, // zero }; - u32 csr = ssetable[mode]; + u32 csr = roundingModeLUT[roundingMode]; + + static const u32 denormalLUT[2] = + { + FTZ, // flush-to-zero only + FTZ | DAZ, // flush-to-zero and denormals-are-zero (may not be supported) + }; + if (nonIEEEMode) + { + csr |= denormalLUT[cpu_info.bFlushToZero]; + } _mm_setcsr(csr); } diff --git a/Source/Core/Core/Core.vcxproj.filters b/Source/Core/Core/Core.vcxproj.filters index ae766cd165..97364678a4 100644 --- a/Source/Core/Core/Core.vcxproj.filters +++ b/Source/Core/Core/Core.vcxproj.filters @@ -133,6 +133,9 @@ {8352be4d-d37d-4f55-adec-b940a9712802} + + {827afa93-1a80-4835-93ae-b5516d95867f} + @@ -636,39 +639,12 @@ PowerPC\JitCommon - - PowerPC\JitIL - PowerPC\JitIL PowerPC\JitIL - - PowerPC\JitIL - - - PowerPC\JitIL - - - PowerPC\JitIL - - - PowerPC\JitIL - - - PowerPC\JitIL - - - PowerPC\JitIL - - - PowerPC\JitIL - - - PowerPC\JitIL - PowerPC\JitIL @@ -706,6 +682,33 @@ PowerPC\Jit64 + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + @@ -1190,9 +1193,6 @@ PowerPC\JitCommon - - PowerPC\JitIL - PowerPC\JitIL @@ -1209,6 +1209,12 @@ PowerPC\Jit64 + + PowerPC\JitILCommon + + + PowerPC\JitILCommon + diff --git a/Source/Core/Core/Src/Console.cpp b/Source/Core/Core/Src/Console.cpp index 15a19b4b74..2d48d0b5c6 100644 --- a/Source/Core/Core/Src/Console.cpp +++ b/Source/Core/Core/Src/Console.cpp @@ -17,8 +17,8 @@ #include "PowerPCDisasm.h" #include "Console.h" -#define CASE1(x) if (memcmp(cmd, x, 2*sizeof(TCHAR))==0) -#define CASE(x) else if (memcmp(cmd, x, 4*sizeof(TCHAR))==0) +#define CASE1(x) if (!strcmp(cmd, (x))) +#define CASE(x) else if (!strcmp(cmd, (x))) void Console_Submit(const char *cmd) { @@ -27,7 +27,7 @@ void Console_Submit(const char *cmd) Core::StartTrace(false); INFO_LOG(CONSOLE, "Read tracing started."); } - CASE1("w") + CASE("w") { Core::StartTrace(true); INFO_LOG(CONSOLE, "Write tracing started."); @@ -141,3 +141,6 @@ void Console_Submit(const char *cmd) ERROR_LOG(CONSOLE, "Invalid command"); } } + +#undef CASE1 +#undef CASE diff --git a/Source/Core/Core/Src/Core.cpp b/Source/Core/Core/Src/Core.cpp index 88c0376cb2..ea54163c30 100644 --- a/Source/Core/Core/Src/Core.cpp +++ b/Source/Core/Core/Src/Core.cpp @@ -388,8 +388,8 @@ void EmuThread() OSD::AddMessage("Dolphin " + g_video_backend->GetName() + " Video Backend.", 5000); - if (!DSP::GetDSPEmulator()->Initialize(_CoreParameter.bWii, - _CoreParameter.bDSPThread)) + if (!DSP::GetDSPEmulator()->Initialize(g_pWindowHandle, + _CoreParameter.bWii, _CoreParameter.bDSPThread)) { HW::Shutdown(); g_video_backend->Shutdown(); diff --git a/Source/Core/Core/Src/CoreParameter.cpp b/Source/Core/Core/Src/CoreParameter.cpp index 4cba012ea4..e7843fe997 100644 --- a/Source/Core/Core/Src/CoreParameter.cpp +++ b/Source/Core/Core/Src/CoreParameter.cpp @@ -18,6 +18,8 @@ #include "Core.h" // for bWii #include "FifoPlayer/FifoDataFile.h" +#include + SCoreStartupParameter::SCoreStartupParameter() : hInstance(0), bEnableDebugging(false), bAutomaticStart(false), bBootToPause(false), @@ -278,7 +280,7 @@ bool SCoreStartupParameter::AutoSetup(EBootBS2 _BootBS2) // Use the TitleIDhex for name and/or unique ID if launching from nand folder // or if it is not ascii characters (specifically sysmenu could potentially apply to other things) char titleidstr[17]; - snprintf(titleidstr, 17, "%016llx", ContentLoader.GetTitleID()); + snprintf(titleidstr, 17, "%016" PRIx64, ContentLoader.GetTitleID()); if (!m_strName.length()) { diff --git a/Source/Core/Core/Src/CoreTiming.cpp b/Source/Core/Core/Src/CoreTiming.cpp index c17e46fc80..6dac07e567 100644 --- a/Source/Core/Core/Src/CoreTiming.cpp +++ b/Source/Core/Core/Src/CoreTiming.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #include "Thread.h" #include "PowerPC/PowerPC.h" @@ -429,7 +430,7 @@ void LogPendingEvents() Event *ptr = first; while (ptr) { - INFO_LOG(POWERPC, "PENDING: Now: %lld Pending: %lld Type: %d", globalTimer, ptr->time, ptr->type); + INFO_LOG(POWERPC, "PENDING: Now: %" PRId64 " Pending: %" PRId64 " Type: %d", globalTimer, ptr->time, ptr->type); ptr = ptr->next; } } diff --git a/Source/Core/Core/Src/DSPEmulator.h b/Source/Core/Core/Src/DSPEmulator.h index 207818cbca..45b2b30c8c 100644 --- a/Source/Core/Core/Src/DSPEmulator.h +++ b/Source/Core/Core/Src/DSPEmulator.h @@ -15,7 +15,7 @@ public: virtual bool IsLLE() = 0; - virtual bool Initialize(bool bWii, bool bDSPThread) = 0; + virtual bool Initialize(void *hWnd, bool bWii, bool bDSPThread) = 0; virtual void Shutdown() = 0; virtual void DoState(PointerWrap &p) = 0; @@ -35,6 +35,7 @@ public: protected: SoundStream *soundStream; + void *m_hWnd; }; DSPEmulator *CreateDSPEmulator(bool HLE); diff --git a/Source/Core/Core/Src/FifoPlayer/FifoDataFile.cpp b/Source/Core/Core/Src/FifoPlayer/FifoDataFile.cpp index 118511af92..5e7e864ad0 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoDataFile.cpp +++ b/Source/Core/Core/Src/FifoPlayer/FifoDataFile.cpp @@ -86,7 +86,7 @@ bool FifoDataFile::Save(const char *filename) header.xfRegsSize = XF_REGS_SIZE; header.frameListOffset = frameListOffset; - header.frameCount = m_Frames.size(); + header.frameCount = (u32)m_Frames.size(); header.flags = m_Flags; @@ -111,7 +111,7 @@ bool FifoDataFile::Save(const char *filename) dstFrame.fifoStart = srcFrame.fifoStart; dstFrame.fifoEnd = srcFrame.fifoEnd; dstFrame.memoryUpdatesOffset = memoryUpdatesOffset; - dstFrame.numMemoryUpdates = srcFrame.memoryUpdates.size(); + dstFrame.numMemoryUpdates = (u32)srcFrame.memoryUpdates.size(); // Write frame info u64 frameOffset = frameListOffset + (i * sizeof(FileFrameInfo)); diff --git a/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.cpp b/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.cpp index 1e606e52e4..e6adc14130 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.cpp +++ b/Source/Core/Core/Src/FifoPlayer/FifoPlaybackAnalyzer.cpp @@ -234,7 +234,7 @@ u32 FifoPlaybackAnalyzer::DecodeCommand(u8 *data) break; } - return data - dataStart; + return (u32)(data - dataStart); } void FifoPlaybackAnalyzer::StoreEfbCopyRegion() diff --git a/Source/Core/Core/Src/FifoPlayer/FifoPlayer.cpp b/Source/Core/Core/Src/FifoPlayer/FifoPlayer.cpp index 0f65c6a966..8aaf962999 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoPlayer.cpp +++ b/Source/Core/Core/Src/FifoPlayer/FifoPlayer.cpp @@ -105,7 +105,9 @@ bool FifoPlayer::Play() u32 FifoPlayer::GetFrameObjectCount() { if (m_CurrentFrame < m_FrameInfo.size()) - return m_FrameInfo[m_CurrentFrame].objectStarts.size(); + { + return (u32)(m_FrameInfo[m_CurrentFrame].objectStarts.size()); + } return 0; } @@ -172,7 +174,7 @@ void FifoPlayer::WriteFrame(const FifoFrameInfo &frame, const AnalyzedFrameInfo m_FrameFifoSize = frame.fifoDataSize; // Determine start and end objects - u32 numObjects = info.objectStarts.size(); + u32 numObjects = (u32)(info.objectStarts.size()); u32 drawStart = std::min(numObjects, m_ObjectRangeStart); u32 drawEnd = std::min(numObjects - 1, m_ObjectRangeEnd); @@ -181,7 +183,9 @@ void FifoPlayer::WriteFrame(const FifoFrameInfo &frame, const AnalyzedFrameInfo // Skip memory updates during frame if true if (m_EarlyMemoryUpdates) - memoryUpdate = frame.memoryUpdates.size(); + { + memoryUpdate = (u32)(frame.memoryUpdates.size()); + } if (numObjects > 0) { diff --git a/Source/Core/Core/Src/FifoPlayer/FifoRecorder.cpp b/Source/Core/Core/Src/FifoPlayer/FifoRecorder.cpp index fb98205d27..e58b34658a 100644 --- a/Source/Core/Core/Src/FifoPlayer/FifoRecorder.cpp +++ b/Source/Core/Core/Src/FifoPlayer/FifoRecorder.cpp @@ -83,9 +83,9 @@ void FifoRecorder::WriteGPCommand(u8 *data, u32 size) if (m_FrameEnded && m_FifoData.size() > 0) { size_t dataSize = m_FifoData.size(); - m_CurrentFrame.fifoDataSize = dataSize; + m_CurrentFrame.fifoDataSize = (u32)dataSize; m_CurrentFrame.fifoData = new u8[dataSize]; - memcpy(m_CurrentFrame.fifoData, &m_FifoData[0], dataSize); + memcpy(m_CurrentFrame.fifoData, m_FifoData.data(), dataSize); sMutex.lock(); @@ -129,7 +129,7 @@ void FifoRecorder::WriteMemory(u32 address, u32 size, MemoryUpdate::Type type) // Record memory update MemoryUpdate memUpdate; memUpdate.address = address; - memUpdate.fifoPosition = m_FifoData.size(); + memUpdate.fifoPosition = (u32)(m_FifoData.size()); memUpdate.size = size; memUpdate.type = type; memUpdate.data = new u8[size]; diff --git a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp index 3897fd6e86..501bc2a0dd 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp +++ b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.cpp @@ -42,8 +42,9 @@ struct DSPState } }; -bool DSPHLE::Initialize(bool bWii, bool bDSPThread) +bool DSPHLE::Initialize(void *hWnd, bool bWii, bool bDSPThread) { + m_hWnd = hWnd; m_bWii = bWii; m_pUCode = NULL; m_lastUCode = NULL; @@ -265,7 +266,7 @@ void DSPHLE::InitMixer() unsigned int AISampleRate, DACSampleRate; AudioInterface::Callback_GetSampleRate(AISampleRate, DACSampleRate); delete soundStream; - soundStream = AudioCommon::InitSoundStream(new HLEMixer(this, AISampleRate, DACSampleRate, 48000)); + soundStream = AudioCommon::InitSoundStream(new HLEMixer(this, AISampleRate, DACSampleRate, 48000), m_hWnd); if(!soundStream) PanicAlert("Error starting up sound stream"); // Mixer is initialized m_InitMixer = true; diff --git a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.h b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.h index 44248fd88f..6627b9dc2a 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.h +++ b/Source/Core/Core/Src/HW/DSPHLE/DSPHLE.h @@ -16,7 +16,7 @@ class DSPHLE : public DSPEmulator { public: DSPHLE(); - virtual bool Initialize(bool bWii, bool bDSPThread) override; + virtual bool Initialize(void *hWnd, bool bWii, bool bDSPThread) override; virtual void Shutdown() override; virtual bool IsLLE() override { return false ; } diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h index 6819b05818..fce6cdf6a2 100644 --- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h +++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h @@ -469,36 +469,42 @@ void ProcessVoice(PB_TYPE& pb, const AXBuffers& buffers, u16 count, AXMixControl // Mix LRS, AUXA and AUXB depending on mixer_control // TODO: Handle DPL2 on AUXB. - if (mctrl & MIX_L) - MixAdd(buffers.left, samples, count, &pb.mixer.left, &pb.dpop.left, mctrl & MIX_L_RAMP); - if (mctrl & MIX_R) - MixAdd(buffers.right, samples, count, &pb.mixer.right, &pb.dpop.right, mctrl & MIX_R_RAMP); - if (mctrl & MIX_S) - MixAdd(buffers.surround, samples, count, &pb.mixer.surround, &pb.dpop.surround, mctrl & MIX_S_RAMP); +#define MIX_ON(C) (0 != (mctrl & MIX_##C)) +#define RAMP_ON(C) (0 != (mctrl & MIX_##C##_RAMP)) - if (mctrl & MIX_AUXA_L) - MixAdd(buffers.auxA_left, samples, count, &pb.mixer.auxA_left, &pb.dpop.auxA_left, mctrl & MIX_AUXA_L_RAMP); - if (mctrl & MIX_AUXA_R) - MixAdd(buffers.auxA_right, samples, count, &pb.mixer.auxA_right, &pb.dpop.auxA_right, mctrl & MIX_AUXA_R_RAMP); - if (mctrl & MIX_AUXA_S) - MixAdd(buffers.auxA_surround, samples, count, &pb.mixer.auxA_surround, &pb.dpop.auxA_surround, mctrl & MIX_AUXA_S_RAMP); + if (MIX_ON(L)) + MixAdd(buffers.left, samples, count, &pb.mixer.left, &pb.dpop.left, RAMP_ON(L)); + if (MIX_ON(R)) + MixAdd(buffers.right, samples, count, &pb.mixer.right, &pb.dpop.right, RAMP_ON(R)); + if (MIX_ON(S)) + MixAdd(buffers.surround, samples, count, &pb.mixer.surround, &pb.dpop.surround, RAMP_ON(S)); - if (mctrl & MIX_AUXB_L) - MixAdd(buffers.auxB_left, samples, count, &pb.mixer.auxB_left, &pb.dpop.auxB_left, mctrl & MIX_AUXB_L_RAMP); - if (mctrl & MIX_AUXB_R) - MixAdd(buffers.auxB_right, samples, count, &pb.mixer.auxB_right, &pb.dpop.auxB_right, mctrl & MIX_AUXB_R_RAMP); - if (mctrl & MIX_AUXB_S) - MixAdd(buffers.auxB_surround, samples, count, &pb.mixer.auxB_surround, &pb.dpop.auxB_surround, mctrl & MIX_AUXB_S_RAMP); + if (MIX_ON(AUXA_L)) + MixAdd(buffers.auxA_left, samples, count, &pb.mixer.auxA_left, &pb.dpop.auxA_left, RAMP_ON(AUXA_L)); + if (MIX_ON(AUXA_R)) + MixAdd(buffers.auxA_right, samples, count, &pb.mixer.auxA_right, &pb.dpop.auxA_right, RAMP_ON(AUXA_R)); + if (MIX_ON(AUXA_S)) + MixAdd(buffers.auxA_surround, samples, count, &pb.mixer.auxA_surround, &pb.dpop.auxA_surround, RAMP_ON(AUXA_S)); + + if (MIX_ON(AUXB_L)) + MixAdd(buffers.auxB_left, samples, count, &pb.mixer.auxB_left, &pb.dpop.auxB_left, RAMP_ON(AUXB_L)); + if (MIX_ON(AUXB_R)) + MixAdd(buffers.auxB_right, samples, count, &pb.mixer.auxB_right, &pb.dpop.auxB_right, RAMP_ON(AUXB_R)); + if (MIX_ON(AUXB_S)) + MixAdd(buffers.auxB_surround, samples, count, &pb.mixer.auxB_surround, &pb.dpop.auxB_surround, RAMP_ON(AUXB_S)); #ifdef AX_WII - if (mctrl & MIX_AUXC_L) - MixAdd(buffers.auxC_left, samples, count, &pb.mixer.auxC_left, &pb.dpop.auxC_left, mctrl & MIX_AUXC_L_RAMP); - if (mctrl & MIX_AUXC_R) - MixAdd(buffers.auxC_right, samples, count, &pb.mixer.auxC_right, &pb.dpop.auxC_right, mctrl & MIX_AUXC_R_RAMP); - if (mctrl & MIX_AUXC_S) - MixAdd(buffers.auxC_surround, samples, count, &pb.mixer.auxC_surround, &pb.dpop.auxC_surround, mctrl & MIX_AUXC_S_RAMP); + if (MIX_ON(AUXC_L)) + MixAdd(buffers.auxC_left, samples, count, &pb.mixer.auxC_left, &pb.dpop.auxC_left, RAMP_ON(AUXC_L)); + if (MIX_ON(AUXC_R)) + MixAdd(buffers.auxC_right, samples, count, &pb.mixer.auxC_right, &pb.dpop.auxC_right, RAMP_ON(AUXC_R)); + if (MIX_ON(AUXC_S)) + MixAdd(buffers.auxC_surround, samples, count, &pb.mixer.auxC_surround, &pb.dpop.auxC_surround, RAMP_ON(AUXC_S)); #endif +#undef MIX_ON +#undef RAMP_ON + // Optionally, phase shift left or right channel to simulate 3D sound. if (pb.initial_time_delay.on) { @@ -524,8 +530,8 @@ void ProcessVoice(PB_TYPE& pb, const AXBuffers& buffers, u16 count, AXMixControl pb.remote_src.cur_addr_frac = curr_pos & 0xFFFF; // Mix to main[0-3] and aux[0-3] -#define WMCHAN_MIX_ON(n) ((pb.remote_mixer_control >> (2 * n)) & 3) -#define WMCHAN_MIX_RAMP(n) ((pb.remote_mixer_control >> (2 * n)) & 2) +#define WMCHAN_MIX_ON(n) (0 != ((pb.remote_mixer_control >> (2 * n)) & 3)) +#define WMCHAN_MIX_RAMP(n) (0 != ((pb.remote_mixer_control >> (2 * n)) & 2)) if (WMCHAN_MIX_ON(0)) MixAdd(buffers.wm_main0, wm_samples, wm_count, &pb.remote_mixer.main0, &pb.remote_dpop.main0, WMCHAN_MIX_RAMP(0)); @@ -544,6 +550,8 @@ void ProcessVoice(PB_TYPE& pb, const AXBuffers& buffers, u16 count, AXMixControl if (WMCHAN_MIX_ON(7)) MixAdd(buffers.wm_aux3, wm_samples, wm_count, &pb.remote_mixer.aux3, &pb.remote_dpop.aux3, WMCHAN_MIX_RAMP(7)); } +#undef WMCHAN_MIX_RAMP +#undef WMCHAN_MIX_ON #endif } diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp index 9b9364947b..af747815d1 100644 --- a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp +++ b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.cpp @@ -130,8 +130,9 @@ void DSPLLE::dsp_thread(DSPLLE *dsp_lle) } } -bool DSPLLE::Initialize(bool bWii, bool bDSPThread) +bool DSPLLE::Initialize(void *hWnd, bool bWii, bool bDSPThread) { + m_hWnd = hWnd; m_bWii = bWii; m_bDSPThread = bDSPThread; m_InitMixer = false; @@ -184,7 +185,7 @@ void DSPLLE::InitMixer() unsigned int AISampleRate, DACSampleRate; AudioInterface::Callback_GetSampleRate(AISampleRate, DACSampleRate); delete soundStream; - soundStream = AudioCommon::InitSoundStream(new CMixer(AISampleRate, DACSampleRate, 48000)); + soundStream = AudioCommon::InitSoundStream(new CMixer(AISampleRate, DACSampleRate, 48000), m_hWnd); if(!soundStream) PanicAlert("Error starting up sound stream"); // Mixer is initialized m_InitMixer = true; diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.h b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.h index 5ae0fd6a74..71addf77b0 100644 --- a/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.h +++ b/Source/Core/Core/Src/HW/DSPLLE/DSPLLE.h @@ -14,7 +14,7 @@ class DSPLLE : public DSPEmulator { public: DSPLLE(); - virtual bool Initialize(bool bWii, bool bDSPThread); + virtual bool Initialize(void *hWnd, bool bWii, bool bDSPThread); virtual void Shutdown(); virtual bool IsLLE() { return true; } diff --git a/Source/Core/Core/Src/HW/DSPLLE/DSPLLEGlobals.cpp b/Source/Core/Core/Src/HW/DSPLLE/DSPLLEGlobals.cpp index 4013ec77c9..c879f5604b 100644 --- a/Source/Core/Core/Src/HW/DSPLLE/DSPLLEGlobals.cpp +++ b/Source/Core/Core/Src/HW/DSPLLE/DSPLLEGlobals.cpp @@ -6,6 +6,7 @@ #include "FileUtil.h" #include "DSP/DSPCore.h" #include "DSPLLEGlobals.h" +#include #if PROFILE @@ -37,12 +38,12 @@ void ProfilerDump(u64 count) File::IOFile pFile("DSP_Prof.txt", "wt"); if (pFile) { - fprintf(pFile.GetHandle(), "Number of DSP steps: %llu\n\n", count); + fprintf(pFile.GetHandle(), "Number of DSP steps: %" PRIu64 "\n\n", count); for (int i=0; i 0) { - fprintf(pFile.GetHandle(), "0x%04X: %llu\n", i, g_profileMap[i]); + fprintf(pFile.GetHandle(), "0x%04X: %" PRIu64 "\n", i, g_profileMap[i]); } } } diff --git a/Source/Core/Core/Src/HW/DVDInterface.cpp b/Source/Core/Core/Src/HW/DVDInterface.cpp index fc326fec90..d77fa4877f 100644 --- a/Source/Core/Core/Src/HW/DVDInterface.cpp +++ b/Source/Core/Core/Src/HW/DVDInterface.cpp @@ -325,7 +325,7 @@ void ChangeDisc(const char* _newFileName) { Movie::g_bDiscChange = true; std::string fileName = _newFileName; - int sizeofpath = fileName.find_last_of("/\\") + 1; + auto sizeofpath = fileName.find_last_of("/\\") + 1; if (fileName.substr(sizeofpath).length() > 40) { PanicAlert("Saving iso filename to .dtm failed; max file name length is 40 characters."); diff --git a/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp b/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp index 1cdeb1fbcf..2d1fb56c2a 100644 --- a/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp +++ b/Source/Core/Core/Src/HW/EXI_DeviceMemoryCard.cpp @@ -191,7 +191,7 @@ void CEXIMemoryCard::CmdDone() void CEXIMemoryCard::CmdDoneLater(u64 cycles) { CoreTiming::RemoveEvent(et_cmd_done); - CoreTiming::ScheduleEvent(cycles, et_cmd_done, (u64)card_index); + CoreTiming::ScheduleEvent((int)cycles, et_cmd_done, (u64)card_index); } void CEXIMemoryCard::SetCS(int cs) diff --git a/Source/Core/Core/Src/HW/GCMemcard.cpp b/Source/Core/Core/Src/HW/GCMemcard.cpp index 22786b3027..d320f0177a 100644 --- a/Source/Core/Core/Src/HW/GCMemcard.cpp +++ b/Source/Core/Core/Src/HW/GCMemcard.cpp @@ -4,6 +4,9 @@ #include "GCMemcard.h" #include "ColorUtil.h" + +#include + static void ByteSwap(u8 *valueA, u8 *valueB) { u8 tmp = *valueA; @@ -37,19 +40,19 @@ GCMemcard::GCMemcard(const char *filename, bool forceCreation, bool sjis) PanicAlertT("File has the extension \"%s\"\nvalid extensions are (.raw/.gcp)", fileType.c_str()); return; } - u32 size = mcdFile.GetSize(); + auto size = mcdFile.GetSize(); if (size < MC_FST_BLOCKS*BLOCK_SIZE) { - PanicAlertT("%s failed to load as a memorycard \nfile is not large enough to be a valid memory card file (0x%x bytes)", filename, size); + PanicAlertT("%s failed to load as a memorycard \nfile is not large enough to be a valid memory card file (0x%x bytes)", filename, (unsigned) size); return; } if (size % BLOCK_SIZE) { - PanicAlertT("%s failed to load as a memorycard \n Card file size is invalid (0x%x bytes)", filename, size); + PanicAlertT("%s failed to load as a memorycard \n Card file size is invalid (0x%x bytes)", filename, (unsigned) size); return; } - m_sizeMb = (size/BLOCK_SIZE) / MBIT_TO_BLOCKS; + m_sizeMb = (u16)((size/BLOCK_SIZE) / MBIT_TO_BLOCKS); switch (m_sizeMb) { case MemCard59Mb: @@ -60,7 +63,7 @@ GCMemcard::GCMemcard(const char *filename, bool forceCreation, bool sjis) case MemCard2043Mb: break; default: - PanicAlertT("%s failed to load as a memorycard \n Card size is invalid (0x%x bytes)", filename, size); + PanicAlertT("%s failed to load as a memorycard \n Card size is invalid (0x%x bytes)", filename, (unsigned) size); return; } } @@ -173,7 +176,7 @@ GCMemcard::GCMemcard(const char *filename, bool forceCreation, bool sjis) } else { - PanicAlertT("Failed to read block %d of the save data\nMemcard may be truncated\nFilePosition:%llx", i, mcdFile.Tell()); + PanicAlertT("Failed to read block %d of the save data\nMemcard may be truncated\nFilePosition:%" PRIx64, i, mcdFile.Tell()); m_valid = false; break; } diff --git a/Source/Core/Core/Src/HW/GCPadEmu.cpp b/Source/Core/Core/Src/HW/GCPadEmu.cpp index 28c33ae926..fa219c369a 100644 --- a/Source/Core/Core/Src/HW/GCPadEmu.cpp +++ b/Source/Core/Core/Src/HW/GCPadEmu.cpp @@ -209,5 +209,5 @@ void GCPad::LoadDefaults(const ControllerInterface& ciface) bool GCPad::GetMicButton() const { - return m_buttons->controls.back()->control_ref->State(); + return (0.0f != m_buttons->controls.back()->control_ref->State()); } diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp index 235d5cb7f1..2014f0b1f4 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/EmuSubroutines.cpp @@ -32,7 +32,7 @@ namespace WiimoteEmu { -void Spy(Wiimote* wm_, const void* data_, int size_) +void Spy(Wiimote* wm_, const void* data_, size_t size_) { #if 0 // enable log @@ -1275,7 +1275,7 @@ void Wiimote::DoState(PointerWrap& p) else { std::queue tmp_queue(m_read_requests); - size = m_read_requests.size(); + size = (u32)(m_read_requests.size()); p.Do(size); while (!tmp_queue.empty()) { diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp index 28f60940c4..4c80b1adda 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.cpp @@ -765,7 +765,7 @@ void Wiimote::Update() if (-1 == rptf_size) { std::copy(rpt.begin(), rpt.end(), data); - rptf_size = rpt.size(); + rptf_size = (s8)(rpt.size()); } } } diff --git a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h index 9ed58f8b48..f2afda4aa3 100644 --- a/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h +++ b/Source/Core/Core/Src/HW/WiimoteEmu/WiimoteEmu.h @@ -96,7 +96,7 @@ inline double trim(double a) class Wiimote : public ControllerEmu { friend class WiimoteReal::Wiimote; -friend void Spy(Wiimote* wm_, const void* data_, int size_); +friend void Spy(Wiimote* wm_, const void* data_, size_t size_); public: enum @@ -245,7 +245,7 @@ private: } m_reg_speaker; }; -void Spy(Wiimote* wm_, const void* data_, int size_); +void Spy(Wiimote* wm_, const void* data_, size_t size_); } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp index ada6237756..57034ff09a 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IODummy.cpp @@ -72,7 +72,7 @@ int Wiimote::IORead(u8* buf) return 0; } -int Wiimote::IOWrite(const u8* buf, int len) +int Wiimote::IOWrite(const u8* buf, size_t len) { return 0; } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp index 860a9a3d57..0f4fe5e730 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IONix.cpp @@ -263,9 +263,9 @@ int Wiimote::IORead(u8* buf) return r; } -int Wiimote::IOWrite(u8 const* buf, int len) +int Wiimote::IOWrite(u8 const* buf, size_t len) { - return write(int_sock, buf, len); + return write(int_sock, buf, (int)len); } }; // WiimoteReal diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp index 2f1efd0228..13728a9d72 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOWin.cpp @@ -140,7 +140,7 @@ namespace WiimoteReal { -int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, int len); +int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, size_t len); int _IORead(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read, u8* buf, int index); void _IOWakeup(HANDLE &dev_handle, OVERLAPPED &hid_overlap_read); @@ -247,7 +247,7 @@ void WiimoteScanner::FindWiimotes(std::vector & found_wiimotes, Wiimot // SLEEP(2000); } -int CheckDeviceType_Write(HANDLE &dev_handle, const u8* buf, int size, int attempts) +int CheckDeviceType_Write(HANDLE &dev_handle, const u8* buf, size_t size, int attempts) { OVERLAPPED hid_overlap_write = OVERLAPPED(); hid_overlap_write.hEvent = CreateEvent(NULL, true, false, NULL); @@ -641,7 +641,7 @@ int Wiimote::IORead(u8* buf) } -int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, int len) +int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stack_t &stack, const u8* buf, size_t len) { WiimoteEmu::Spy(NULL, buf, len); @@ -663,7 +663,7 @@ int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stac } case MSBT_STACK_MS: { - auto result = HidD_SetOutputReport(dev_handle, const_cast(buf) + 1, len - 1); + auto result = HidD_SetOutputReport(dev_handle, const_cast(buf) + 1, (ULONG)(len - 1)); //FlushFileBuffers(dev_handle); if (!result) @@ -715,7 +715,7 @@ int _IOWrite(HANDLE &dev_handle, OVERLAPPED &hid_overlap_write, enum win_bt_stac return 0; } -int Wiimote::IOWrite(const u8* buf, int len) +int Wiimote::IOWrite(const u8* buf, size_t len) { return _IOWrite(dev_handle, hid_overlap_write, stack, buf, len); } diff --git a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm index f59cffee2c..c094c97c13 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm +++ b/Source/Core/Core/Src/HW/WiimoteReal/IOdarwin.mm @@ -310,14 +310,14 @@ int Wiimote::IORead(unsigned char *buf) return inputlen; } -int Wiimote::IOWrite(const unsigned char *buf, int len) +int Wiimote::IOWrite(const unsigned char *buf, size_t len) { IOReturn ret; if (!IsConnected()) return 0; - ret = [ichan writeAsync: const_cast((void *)buf) length: len refcon: nil]; + ret = [ichan writeAsync: const_cast((void *)buf) length: (int)len refcon: nil]; if (ret == kIOReturnSuccess) return len; diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp index e5fff5b3f1..dea6f7fce6 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.cpp @@ -239,7 +239,9 @@ bool Wiimote::Write() IOWrite(rpt.data(), rpt.size()); if (is_speaker_data) + { m_last_audio_report.Update(); + } m_write_reports.Pop(); return true; @@ -293,8 +295,10 @@ void Wiimote::Update() // Send the report if (!rpt.empty() && m_channel > 0) - Core::Callback_WiimoteInterruptChannel(index, m_channel, - rpt.data(), rpt.size()); + { + Core::Callback_WiimoteInterruptChannel(index, m_channel, + rpt.data(), (u32)rpt.size()); + } } void Wiimote::Prepare(int _index) diff --git a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h index c4807ed95f..bc953102a9 100644 --- a/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h +++ b/Source/Core/Core/Src/HW/WiimoteReal/WiimoteReal.h @@ -106,7 +106,7 @@ private: void WriteReport(Report rpt); int IORead(u8* buf); - int IOWrite(u8 const* buf, int len); + int IOWrite(u8 const* buf, size_t len); void IOWakeup(); void ThreadFunc(); diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp index 22115e4900..3bd37ba373 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE.cpp @@ -83,7 +83,7 @@ static u64 last_reply_time; void EnqueReplyCallback(u64 userdata, int) { std::lock_guard lk(s_reply_queue); - reply_queue.push_back(userdata); + reply_queue.push_back((u32)userdata); } void Init() @@ -546,7 +546,9 @@ void ExecuteCommand(u32 _Address) const s64 ticks_til_last_reply = last_reply_time - CoreTiming::GetTicks(); if (ticks_til_last_reply > 0) - reply_delay = ticks_til_last_reply; + { + reply_delay = (int)ticks_til_last_reply; + } last_reply_time = CoreTiming::GetTicks() + reply_delay; diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp index 9b6cf8ac8e..e0106bf273 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_DI.cpp @@ -19,6 +19,8 @@ #include "../../DiscIO/Src/FileMonitor.h" +#include + using namespace DVDInterface; @@ -108,7 +110,7 @@ bool CWII_IPC_HLE_Device_di::IOCtlV(u32 _CommandAddress) // Get TMD offset for requested partition... u64 const TMDOffset = ((u64)Memory::Read_U32(CommandBuffer.InBuffer[0].m_Address + 4) << 2 ) + 0x2c0; - INFO_LOG(WII_IPC_DVD, "DVDLowOpenPartition: TMDOffset 0x%016llx", TMDOffset); + INFO_LOG(WII_IPC_DVD, "DVDLowOpenPartition: TMDOffset 0x%016" PRIx64, TMDOffset); static u32 const TMDsz = 0x208; //CommandBuffer.PayloadBuffer[0].m_Size; u8 pTMD[TMDsz]; @@ -204,13 +206,13 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 pFilename = m_pFileSystem->GetFileName(DVDAddress); if (pFilename != NULL) { - INFO_LOG(WII_IPC_DVD, "DVDLowRead: %s (0x%llx) - (DVDAddr: 0x%llx, Size: 0x%x)", + INFO_LOG(WII_IPC_DVD, "DVDLowRead: %s (0x%" PRIx64 ") - (DVDAddr: 0x%" PRIx64 ", Size: 0x%x)", pFilename, m_pFileSystem->GetFileSize(pFilename), DVDAddress, Size); FileMon::CheckFile(std::string(pFilename), (int)m_pFileSystem->GetFileSize(pFilename)); } else { - INFO_LOG(WII_IPC_DVD, "DVDLowRead: file unknown - (DVDAddr: 0x%llx, Size: 0x%x)", + INFO_LOG(WII_IPC_DVD, "DVDLowRead: file unknown - (DVDAddr: 0x%" PRIx64 ", Size: 0x%x)", DVDAddress, Size); } } @@ -308,7 +310,7 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 u64 DVDAddress = (u64)DVDAddress32 << 2; - INFO_LOG(WII_IPC_DVD, "DVDLowUnencryptedRead: DVDAddr: 0x%08llx, Size: 0x%x", DVDAddress, Size); + INFO_LOG(WII_IPC_DVD, "DVDLowUnencryptedRead: DVDAddr: 0x%08" PRIx64 ", Size: 0x%x", DVDAddress, Size); if (Size > _BufferOutSize) { @@ -342,12 +344,12 @@ u32 CWII_IPC_HLE_Device_di::ExecuteCommand(u32 _BufferIn, u32 _BufferInSize, u32 pFilename = m_pFileSystem->GetFileName(DVDAddress); if (pFilename != NULL) { - INFO_LOG(WII_IPC_DVD, "DVDLowSeek: %s (0x%llx) - (DVDAddr: 0x%llx)", + INFO_LOG(WII_IPC_DVD, "DVDLowSeek: %s (0x%" PRIx64 ") - (DVDAddr: 0x%" PRIx64 ")", pFilename, m_pFileSystem->GetFileSize(pFilename), DVDAddress); } else { - INFO_LOG(WII_IPC_DVD, "DVDLowSeek: file unknown - (DVDAddr: 0x%llx)", + INFO_LOG(WII_IPC_DVD, "DVDLowSeek: file unknown - (DVDAddr: 0x%" PRIx64 ")", DVDAddress); } } diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp index 151010e8fa..ea4230f485 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_es.cpp @@ -35,6 +35,10 @@ #include "WII_IPC_HLE_Device_es.h" +// need to include this before polarssl/aes.h, +// otherwise we may not get __STDC_FORMAT_MACROS +#include + #include "../PowerPC/PowerPC.h" #include "../VolumeHandler.h" #include "FileUtil.h" @@ -129,7 +133,7 @@ void CWII_IPC_HLE_Device_es::DoState(PointerWrap& p) p.Do(m_AccessIdentID); p.Do(m_TitleIDs); - u32 Count = m_ContentAccessMap.size(); + u32 Count = (u32)(m_ContentAccessMap.size()); p.Do(Count); u32 CFD, Position; @@ -205,7 +209,7 @@ u32 CWII_IPC_HLE_Device_es::OpenTitleContent(u32 CFD, u64 TitleID, u16 Index) if (!Loader.IsValid()) { - WARN_LOG(WII_IPC_ES, "ES: loader not valid for %llx", TitleID); + WARN_LOG(WII_IPC_ES, "ES: loader not valid for %" PRIx64, TitleID); return 0xffffffff; } @@ -940,7 +944,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) if (!bSuccess) { PanicAlertT("IOCTL_ES_LAUNCH: Game tried to reload a title that is not available in your NAND dump\n" - "TitleID %016llx.\n Dolphin will likely hang now.", TitleID); + "TitleID %016" PRIx64".\n Dolphin will likely hang now.", TitleID); } else { @@ -983,7 +987,7 @@ bool CWII_IPC_HLE_Device_es::IOCtlV(u32 _CommandAddress) //TODO: provide correct return code when bSuccess= false Memory::Write_U32(0, _CommandAddress + 0x4); - ERROR_LOG(WII_IPC_ES, "IOCTL_ES_LAUNCH %016llx %08x %016llx %08x %016llx %04x", TitleID,view,ticketid,devicetype,titleid,access); + ERROR_LOG(WII_IPC_ES, "IOCTL_ES_LAUNCH %016" PRIx64 " %08x %016" PRIx64 " %08x %016" PRIx64 " %04x", TitleID,view,ticketid,devicetype,titleid,access); // IOCTL_ES_LAUNCH 0001000248414341 00000001 0001c0fef3df2cfa 00000000 0001000248414341 ffff // This is necessary because Reset(true) above deleted this object. Ew. diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp index edbcc0967a..4de7af8e06 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_fs.cpp @@ -571,7 +571,7 @@ void CWII_IPC_HLE_Device_fs::DoState(PointerWrap& p) } else { - u32 size = entry.size; + u32 size = (u32)entry.size; p.Do(size); File::IOFile handle(entry.physicalName, "rb"); diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp index 00415a526f..c1b82e4d55 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_hid.cpp @@ -385,12 +385,12 @@ void CWII_IPC_HLE_Device_hid::FillOutDevices(u32 BufferOut, u32 BufferOutSize) Memory::WriteBigEData((const u8*)&wii_device, OffsetBuffer, Align(wii_device.bLength, 4)); OffsetBuffer += Align(wii_device.bLength, 4); bool deviceValid = true; + bool isHID = false; for (c = 0; deviceValid && c < desc.bNumConfigurations; c++) { struct libusb_config_descriptor *config = NULL; int cRet = libusb_get_config_descriptor(device, c, &config); - // do not try to use usb devices with more than one interface, games can crash if(cRet == 0 && config->bNumInterfaces <= MAX_HID_INTERFACES) { @@ -402,10 +402,14 @@ void CWII_IPC_HLE_Device_hid::FillOutDevices(u32 BufferOut, u32 BufferOutSize) for (ic = 0; ic < config->bNumInterfaces; ic++) { const struct libusb_interface *interfaceContainer = &config->interface[ic]; + for (i = 0; i < interfaceContainer->num_altsetting; i++) { const struct libusb_interface_descriptor *interface = &interfaceContainer->altsetting[i]; + if (interface->bInterfaceClass == LIBUSB_CLASS_HID) + isHID = true; + WiiHIDInterfaceDescriptor wii_interface; ConvertInterfaceToWii(&wii_interface, interface); Memory::WriteBigEData((const u8*)&wii_interface, OffsetBuffer, Align(wii_interface.bLength, 4)); @@ -435,6 +439,12 @@ void CWII_IPC_HLE_Device_hid::FillOutDevices(u32 BufferOut, u32 BufferOutSize) } } // configs + if (!isHID) + { + deviceValid = false; + OffsetBuffer = OffsetStart; + } + if (deviceValid) { Memory::Write_U32(OffsetBuffer-OffsetStart, OffsetStart); // fill in length diff --git a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp index 990a9e6a7d..aa7d84d661 100644 --- a/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp +++ b/Source/Core/Core/Src/IPC_HLE/WII_IPC_HLE_Device_usb.cpp @@ -866,7 +866,7 @@ bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventRoleChange(bdaddr_t _bd, bool bool CWII_IPC_HLE_Device_usb_oh1_57e_305::SendEventNumberOfCompletedPackets() { - SQueuedEvent Event(sizeof(hci_event_hdr_t) + sizeof(hci_num_compl_pkts_ep) + sizeof(hci_num_compl_pkts_info) * m_WiiMotes.size(), 0); + SQueuedEvent Event((u32)(sizeof(hci_event_hdr_t) + sizeof(hci_num_compl_pkts_ep) + (sizeof(hci_num_compl_pkts_info) * m_WiiMotes.size())), 0); INFO_LOG(WII_IPC_WIIMOTE, "Event: SendEventNumberOfCompletedPackets"); diff --git a/Source/Core/Core/Src/IPC_HLE/hci.h b/Source/Core/Core/Src/IPC_HLE/hci.h index 8923f68fb4..41f145a8ed 100644 --- a/Source/Core/Core/Src/IPC_HLE/hci.h +++ b/Source/Core/Core/Src/IPC_HLE/hci.h @@ -84,14 +84,6 @@ // All structs in this file are packed #pragma pack(push, 1) -/* - * Bluetooth Address Family Protocol Numbers - */ -#define BTPROTO_HCI 1 -#define BTPROTO_L2CAP 2 -#define BTPROTO_RFCOMM 3 -#define BTPROTO_SCO 4 - /* All sizes are in bytes */ #define BLUETOOTH_BDADDR_SIZE 6 @@ -102,9 +94,8 @@ typedef struct { uint8_t b[BLUETOOTH_BDADDR_SIZE]; } bdaddr_t; -#endif - #define BDADDR_ANY { { 0, 0, 0, 0, 0, 0 } } +#endif /************************************************************************** ************************************************************************** diff --git a/Source/Core/Core/Src/NetPlayClient.cpp b/Source/Core/Core/Src/NetPlayClient.cpp index 7e71584c35..6ca13b4836 100644 --- a/Source/Core/Core/Src/NetPlayClient.cpp +++ b/Source/Core/Core/Src/NetPlayClient.cpp @@ -445,10 +445,11 @@ void NetPlayClient::SendWiimoteState(const PadMapping in_game_pad, const NetWiim sf::Packet spac; spac << (MessageId)NP_MSG_WIIMOTE_DATA; spac << in_game_pad; - u8 size = nw.size(); - spac << size; - for (unsigned int i = 0; i < size; ++i) - spac << nw.data()[i]; + spac << (u8)nw.size(); + for (auto it : nw) + { + spac << it; + } std::lock_guard lks(m_crit.send); m_socket.Send(spac); diff --git a/Source/Core/Core/Src/NetPlayServer.cpp b/Source/Core/Core/Src/NetPlayServer.cpp index 0049719a05..296fcd29a4 100644 --- a/Source/Core/Core/Src/NetPlayServer.cpp +++ b/Source/Core/Core/Src/NetPlayServer.cpp @@ -153,7 +153,7 @@ unsigned int NetPlayServer::OnConnect(sf::SocketTCP& socket) rpac >> player.name; // give new client first available id - player.pid = m_players.size() + 1; + player.pid = (PlayerId)(m_players.size() + 1); // try to automatically assign new user a pad for (unsigned int m = 0; m < 4; ++m) @@ -435,12 +435,14 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, sf::SocketTCP& socket) case NP_MSG_PONG : { - const u32 ping = m_ping_timer.GetTimeElapsed(); + const u32 ping = (u32)m_ping_timer.GetTimeElapsed(); u32 ping_key = 0; packet >> ping_key; if (m_ping_key == ping_key) + { player.ping = ping; + } sf::Packet spac; spac << (MessageId)NP_MSG_PLAYER_PING_DATA; diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp index 0082d9946b..dd71abcaeb 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter.cpp @@ -10,11 +10,11 @@ #include "../../Host.h" #include "../../IPC_HLE/WII_IPC_HLE.h" - #ifdef USE_GDBSTUB #include "../GDBStub.h" #endif +#include namespace { u32 last_pc; @@ -79,7 +79,7 @@ void Trace( UGeckoInstruction &instCode ) std::string fregs = ""; for (int i=0; i<32; i++) { - sprintf(freg, "f%02d: %08llx %08llx ", i, PowerPC::ppcState.ps[i][0], PowerPC::ppcState.ps[i][1]); + sprintf(freg, "f%02d: %08" PRIx64 " %08" PRIx64 " ", i, PowerPC::ppcState.ps[i][0], PowerPC::ppcState.ps[i][1]); fregs.append(freg); } diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FPUtils.h b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FPUtils.h index d379bf7049..9190a18ed7 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FPUtils.h +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_FPUtils.h @@ -5,6 +5,7 @@ #ifndef _INTERPRETER_FPUTILS_H #define _INTERPRETER_FPUTILS_H +#include "CPUDetect.h" #include "Interpreter.h" #include "MathUtil.h" @@ -69,28 +70,22 @@ inline void UpdateFPSCR() inline double ForceSingle(double _x) { - //if (FPSCR.RN != 0) - // PanicAlert("RN = %d at %x", (int)FPSCR.RN, PC); - if (FPSCR.NI) - _x = FlushToZeroAsFloat(_x); - - double x = static_cast(_x); - + // convert to float... + float x = _x; + if (!cpu_info.bFlushToZero && FPSCR.NI) + { + x = FlushToZero(x); + } + // ...and back to double: return x; } inline double ForceDouble(double d) { - //if (FPSCR.RN != 0) - // PanicAlert("RN = %d at %x", (int)FPSCR.RN, PC); - - //if (FPSCR.NI) - //{ - // IntDouble x; x.d = d; - //if ((x.i & DOUBLE_EXP) == 0) - // x.i &= DOUBLE_SIGN; // turn into signed zero - // return x.d; - //} + if (!cpu_info.bFlushToZero && FPSCR.NI) + { + d = FlushToZero(d); + } return d; } diff --git a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp index 688d166608..475f7591ce 100644 --- a/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp +++ b/Source/Core/Core/Src/PowerPC/Interpreter/Interpreter_SystemRegisters.cpp @@ -48,15 +48,8 @@ static void FPSCRtoFPUSettings(UReg_FPSCR fp) // Pokemon Colosseum does this. Gah. } - // Also corresponding SSE rounding mode setting - if (FPSCR.NI) - { - // Either one of these two breaks Beyond Good & Evil. - // if (cpu_info.bSSSE3) - // csr |= DAZ; - // csr |= FTZ; - } - FPURoundMode::SetSIMDMode(FPSCR.RN); + // Set SSE rounding mode and denormal handling + FPURoundMode::SetSIMDMode(FPSCR.RN, FPSCR.NI); } void Interpreter::mtfsb0x(UGeckoInstruction _inst) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h index b4997be74b..1adbdfaac4 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit.h @@ -119,7 +119,7 @@ public: void tri_op(int d, int a, int b, bool reversible, void (XEmitter::*op)(Gen::X64Reg, Gen::OpArg)); typedef u32 (*Operation)(u32 a, u32 b); void regimmop(int d, int a, bool binary, u32 value, Operation doop, void (XEmitter::*op)(int, const Gen::OpArg&, const Gen::OpArg&), bool Rc = false, bool carry = false); - void fp_tri_op(int d, int a, int b, bool reversible, bool dupe, void (XEmitter::*op)(Gen::X64Reg, Gen::OpArg)); + void fp_tri_op(int d, int a, int b, bool reversible, bool dupe, void (XEmitter::*op_2)(Gen::X64Reg, Gen::OpArg), void (XEmitter::*op_3)(Gen::X64Reg, Gen::X64Reg, Gen::OpArg)); // OPCODES void unknown_instruction(UGeckoInstruction _inst); @@ -182,7 +182,7 @@ public: void ps_sum(UGeckoInstruction inst); void ps_muls(UGeckoInstruction inst); - void fp_arith_s(UGeckoInstruction inst); + void fp_arith(UGeckoInstruction inst); void frsqrtex(UGeckoInstruction inst); void fcmpx(UGeckoInstruction inst); diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp index 0ff2bf5d7f..dc81015573 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit64_Tables.cpp @@ -320,12 +320,12 @@ static GekkoOPTemplate table31_2[] = static GekkoOPTemplate table59[] = { - {18, &Jit64::Default}, //{"fdivsx", OPTYPE_FPU, FL_RC_BIT_F, 16}}, - {20, &Jit64::fp_arith_s}, //"fsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, - {21, &Jit64::fp_arith_s}, //"faddsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {18, &Jit64::fp_arith}, //{"fdivsx", OPTYPE_FPU, FL_RC_BIT_F, 16}}, + {20, &Jit64::fp_arith}, //"fsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {21, &Jit64::fp_arith}, //"faddsx", OPTYPE_FPU, FL_RC_BIT_F}}, // {22, &Jit64::Default}, //"fsqrtsx", OPTYPE_FPU, FL_RC_BIT_F}}, // Not implemented on gekko {24, &Jit64::Default}, //"fresx", OPTYPE_FPU, FL_RC_BIT_F}}, - {25, &Jit64::fp_arith_s}, //"fmulsx", OPTYPE_FPU, FL_RC_BIT_F}}, + {25, &Jit64::fp_arith}, //"fmulsx", OPTYPE_FPU, FL_RC_BIT_F}}, {28, &Jit64::fmaddXX}, //"fmsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, {29, &Jit64::fmaddXX}, //"fmaddsx", OPTYPE_FPU, FL_RC_BIT_F}}, {30, &Jit64::fmaddXX}, //"fnmsubsx", OPTYPE_FPU, FL_RC_BIT_F}}, @@ -354,12 +354,12 @@ static GekkoOPTemplate table63[] = static GekkoOPTemplate table63_2[] = { - {18, &Jit64::Default}, //"fdivx", OPTYPE_FPU, FL_RC_BIT_F, 30}}, - {20, &Jit64::Default}, //"fsubx", OPTYPE_FPU, FL_RC_BIT_F}}, - {21, &Jit64::Default}, //"faddx", OPTYPE_FPU, FL_RC_BIT_F}}, + {18, &Jit64::fp_arith}, //"fdivx", OPTYPE_FPU, FL_RC_BIT_F, 30}}, + {20, &Jit64::fp_arith}, //"fsubx", OPTYPE_FPU, FL_RC_BIT_F}}, + {21, &Jit64::fp_arith}, //"faddx", OPTYPE_FPU, FL_RC_BIT_F}}, {22, &Jit64::Default}, //"fsqrtx", OPTYPE_FPU, FL_RC_BIT_F}}, {23, &Jit64::Default}, //"fselx", OPTYPE_FPU, FL_RC_BIT_F}}, - {25, &Jit64::fp_arith_s}, //"fmulx", OPTYPE_FPU, FL_RC_BIT_F}}, + {25, &Jit64::fp_arith}, //"fmulx", OPTYPE_FPU, FL_RC_BIT_F}}, {26, &Jit64::frsqrtex}, //"frsqrtex", OPTYPE_FPU, FL_RC_BIT_F}}, {28, &Jit64::fmaddXX}, //"fmsubx", OPTYPE_FPU, FL_RC_BIT_F}}, {29, &Jit64::fmaddXX}, //"fmaddx", OPTYPE_FPU, FL_RC_BIT_F}}, diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp b/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp index f804877627..1be04a0d5d 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.cpp @@ -166,7 +166,7 @@ int RegCache::SanityCheck() const void RegCache::DiscardRegContentsIfCached(int preg) { - if (regs[preg].away && regs[preg].location.IsSimpleReg()) + if (IsBound(preg)) { X64Reg xr = regs[preg].location.GetSimpleReg(); xregs[xr].free = true; @@ -351,11 +351,12 @@ void FPURegCache::StoreFromRegister(int i) { X64Reg xr = regs[i].location.GetSimpleReg(); _assert_msg_(DYNA_REC, xr < NUMXREGS, "WTF - store - invalid reg"); + OpArg newLoc = GetDefaultLocation(i); + if (xregs[xr].dirty) + emit->MOVAPD(newLoc, xr); xregs[xr].free = true; xregs[xr].dirty = false; xregs[xr].ppcReg = -1; - OpArg newLoc = GetDefaultLocation(i); - emit->MOVAPD(newLoc, xr); regs[i].location = newLoc; regs[i].away = false; } diff --git a/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.h b/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.h index cacd1e0e4e..f27dcae91c 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.h +++ b/Source/Core/Core/Src/PowerPC/Jit64/JitRegCache.h @@ -93,7 +93,7 @@ public: const OpArg &R(int preg) const {return regs[preg].location;} X64Reg RX(int preg) const { - if (regs[preg].away && regs[preg].location.IsSimpleReg()) + if (IsBound(preg)) return regs[preg].location.GetSimpleReg(); PanicAlert("Not so simple - %i", preg); return (X64Reg)-1; @@ -111,6 +111,11 @@ public: return xregs[xreg].free && !xlocks[xreg]; } + bool IsBound(int preg) const + { + return regs[preg].away && regs[preg].location.IsSimpleReg(); + } + X64Reg GetFreeXReg(); diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp index ec8ddc63d3..7f77112ae9 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_FloatingPoint.cpp @@ -13,37 +13,62 @@ static const u64 GC_ALIGNED16(psAbsMask2[2]) = {0x7FFFFFFFFFFFFFFFULL, 0x7FFFFF static const double GC_ALIGNED16(psOneOne2[2]) = {1.0, 1.0}; static const double one_const = 1.0f; -void Jit64::fp_tri_op(int d, int a, int b, bool reversible, bool dupe, void (XEmitter::*op)(Gen::X64Reg, Gen::OpArg)) +void Jit64::fp_tri_op(int d, int a, int b, bool reversible, bool single, + void (XEmitter::*op_2)(Gen::X64Reg, Gen::OpArg), + void (XEmitter::*op_3)(Gen::X64Reg, Gen::X64Reg, Gen::OpArg)) { + if (!cpu_info.bAVX) + { + op_3 = nullptr; + } + fpr.Lock(d, a, b); if (d == a) { - fpr.BindToRegister(d, true); - (this->*op)(fpr.RX(d), fpr.R(b)); + fpr.BindToRegister(d); + (this->*op_2)(fpr.RX(d), fpr.R(b)); } else if (d == b) { if (reversible) { - fpr.BindToRegister(d, true); - (this->*op)(fpr.RX(d), fpr.R(a)); + fpr.BindToRegister(d); + (this->*op_2)(fpr.RX(d), fpr.R(a)); } else { - MOVSD(XMM0, fpr.R(b)); - fpr.BindToRegister(d, !dupe); - MOVSD(fpr.RX(d), fpr.R(a)); - (this->*op)(fpr.RX(d), Gen::R(XMM0)); + if (op_3) + { + fpr.BindToRegister(d); + fpr.BindToRegister(a, true, false); + (this->*op_3)(fpr.RX(d), fpr.RX(a), fpr.R(b)); + } + else + { + MOVSD(XMM0, fpr.R(b)); + fpr.BindToRegister(d, false); + MOVSD(fpr.RX(d), fpr.R(a)); + (this->*op_2)(fpr.RX(d), Gen::R(XMM0)); + } } } else { - // Sources different from d, can use rather quick solution - fpr.BindToRegister(d, !dupe); - MOVSD(fpr.RX(d), fpr.R(a)); - (this->*op)(fpr.RX(d), fpr.R(b)); + if (op_3) + { + fpr.BindToRegister(d, false); + fpr.BindToRegister(a); + (this->*op_3)(fpr.RX(d), fpr.RX(a), fpr.R(b)); + } + else + { + fpr.BindToRegister(d, false); + MOVSD(fpr.RX(d), fpr.R(a)); + (this->*op_2)(fpr.RX(d), fpr.R(b)); + } } - if (dupe) + + if (single) { ForceSinglePrecisionS(fpr.RX(d)); if (cpu_info.bSSE3) @@ -60,7 +85,7 @@ void Jit64::fp_tri_op(int d, int a, int b, bool reversible, bool dupe, void (XEm fpr.UnlockAll(); } -void Jit64::fp_arith_s(UGeckoInstruction inst) +void Jit64::fp_arith(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(bJITFloatingPointOff) @@ -73,31 +98,38 @@ void Jit64::fp_arith_s(UGeckoInstruction inst) Default(inst); return; } - bool dupe = inst.OPCD == 59; + bool single = inst.OPCD == 59; switch (inst.SUBOP5) { - case 18: fp_tri_op(inst.FD, inst.FA, inst.FB, false, dupe, &XEmitter::DIVSD); break; //div - case 20: fp_tri_op(inst.FD, inst.FA, inst.FB, false, dupe, &XEmitter::SUBSD); break; //sub - case 21: fp_tri_op(inst.FD, inst.FA, inst.FB, true, dupe, &XEmitter::ADDSD); break; //add - case 25: fp_tri_op(inst.FD, inst.FA, inst.FC, true, dupe, &XEmitter::MULSD); break; //mul + case 18: fp_tri_op(inst.FD, inst.FA, inst.FB, false, single, &XEmitter::DIVSD, &XEmitter::VDIVSD); break; //div + case 20: fp_tri_op(inst.FD, inst.FA, inst.FB, false, single, &XEmitter::SUBSD, &XEmitter::VSUBSD); break; //sub + case 21: fp_tri_op(inst.FD, inst.FA, inst.FB, true, single, &XEmitter::ADDSD, &XEmitter::VADDSD); break; //add + case 25: fp_tri_op(inst.FD, inst.FA, inst.FC, true, single, &XEmitter::MULSD, &XEmitter::VMULSD); break; //mul default: - _assert_msg_(DYNA_REC, 0, "fp_arith_s WTF!!!"); + _assert_msg_(DYNA_REC, 0, "fp_arith WTF!!!"); } } void Jit64::frsqrtex(UGeckoInstruction inst) { - INSTRUCTION_START - JITDISABLE(bJITFloatingPointOff) - int d = inst.FD; - int b = inst.FB; - fpr.Lock(b, d); - fpr.BindToRegister(d, true, true); - MOVSD(XMM0, M((void *)&one_const)); - SQRTSD(XMM1, fpr.R(b)); - DIVSD(XMM0, R(XMM1)); - MOVSD(fpr.R(d), XMM0); - fpr.UnlockAll(); + INSTRUCTION_START + JITDISABLE(bJITFloatingPointOff) + int d = inst.FD; + int b = inst.FB; + fpr.Lock(b, d); + fpr.BindToRegister(d, d == b, true); + MOVSD(XMM0, M((void *)&one_const)); + SQRTSD(XMM1, fpr.R(b)); + if (cpu_info.bAVX) + { + VDIVSD(fpr.RX(d), XMM0, R(XMM1)); + } + else + { + DIVSD(XMM0, R(XMM1)); + MOVSD(fpr.R(d), XMM0); + } + fpr.UnlockAll(); } void Jit64::fmaddXX(UGeckoInstruction inst) @@ -192,16 +224,28 @@ void Jit64::fmrx(UGeckoInstruction inst) { INSTRUCTION_START JITDISABLE(bJITFloatingPointOff) - if (inst.Rc) { + if (inst.Rc) + { Default(inst); return; } int d = inst.FD; int b = inst.FB; - fpr.Lock(b, d); - fpr.BindToRegister(d, true, true); - MOVSD(XMM0, fpr.R(b)); - MOVSD(fpr.R(d), XMM0); - fpr.UnlockAll(); + if (d != b) + { + fpr.Lock(b, d); + + // we don't need to load d, but if it already is, it must be marked as dirty + if (fpr.IsBound(d)) + { + fpr.BindToRegister(d); + } + fpr.BindToRegister(b, true, false); + + // caveat: the order of ModRM:r/m, ModRM:reg is deliberate! + // "MOVSD reg, mem" zeros out the upper half of the destination register + MOVSD(fpr.R(d), fpr.RX(b)); + fpr.UnlockAll(); + } } void Jit64::fcmpx(UGeckoInstruction inst) diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp index e881b5e7e8..a2cb0784d1 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_LoadStorePaired.cpp @@ -122,12 +122,6 @@ void Jit64::psq_l(UGeckoInstruction inst) const UGQR gqr(rSPR(SPR_GQR0 + inst.I)); - if (inst.W) { - // PanicAlert("Single ps load: %i %i", gqr.ST_TYPE, gqr.ST_SCALE); - Default(inst); - return; - } - bool update = inst.OPCD == 57; int offset = inst.SIMM_12; @@ -143,6 +137,8 @@ void Jit64::psq_l(UGeckoInstruction inst) MOV(32, gpr.R(inst.RA), R(ECX)); MOVZX(32, 16, EAX, M(((char *)&GQR(inst.I)) + 2)); MOVZX(32, 8, EDX, R(AL)); + if (inst.W) + OR(32, R(EDX), Imm8(8)); #ifdef _M_IX86 int addr_scale = SCALE_4; #else diff --git a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Paired.cpp b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Paired.cpp index 96a3335249..781b75a538 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64/Jit_Paired.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64/Jit_Paired.cpp @@ -14,10 +14,9 @@ // cmppd, andpd, andnpd, or // lfsx, ps_merge01 etc -const u64 GC_ALIGNED16(psSignBits[2]) = {0x8000000000000000ULL, 0x8000000000000000ULL}; -const u64 GC_ALIGNED16(psAbsMask[2]) = {0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL}; -const double GC_ALIGNED16(psOneOne[2]) = {1.0, 1.0}; -const double GC_ALIGNED16(psZeroZero[2]) = {0.0, 0.0}; +static const u64 GC_ALIGNED16(psSignBits[2]) = {0x8000000000000000ULL, 0x8000000000000000ULL}; +static const u64 GC_ALIGNED16(psAbsMask[2]) = {0x7FFFFFFFFFFFFFFFULL, 0x7FFFFFFFFFFFFFFFULL}; +static const double GC_ALIGNED16(psOneOne[2]) = {1.0, 1.0}; void Jit64::ps_mr(UGeckoInstruction inst) { @@ -52,14 +51,15 @@ void Jit64::ps_sel(UGeckoInstruction inst) fpr.Lock(a, b, c, d); MOVAPD(XMM0, fpr.R(a)); + XORPD(XMM1, R(XMM1)); // XMM0 = XMM0 < 0 ? all 1s : all 0s - CMPPD(XMM0, M((void*)psZeroZero), LT); + CMPPD(XMM0, R(XMM1), LT); MOVAPD(XMM1, R(XMM0)); ANDPD(XMM0, fpr.R(b)); ANDNPD(XMM1, fpr.R(c)); + ORPD(XMM0, R(XMM1)); fpr.BindToRegister(d, false); MOVAPD(fpr.RX(d), R(XMM0)); - ORPD(fpr.RX(d), R(XMM1)); fpr.UnlockAll(); } diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp index b086c02038..ef1db98de1 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/IR_X86.cpp @@ -470,7 +470,7 @@ static void regEmitMemLoad(RegInfo& RI, InstLoc I, unsigned Size) { X64Reg reg; auto info = regBuildMemAddress(RI, I, getOp1(I), 1, Size, ®); - RI.Jit->SafeLoadToReg(reg, info.first, Size, info.second, regsInUse(RI), false); + RI.Jit->SafeLoadToReg(reg, info.first, Size, info.second, regsInUse(RI), false, EmuCodeBlock::SAFE_LOADSTORE_NO_FASTMEM); if (regReadUse(RI, I)) RI.regs[reg] = I; } @@ -498,7 +498,7 @@ static void regEmitMemStore(RegInfo& RI, InstLoc I, unsigned Size) { } else { RI.Jit->MOV(32, R(EAX), regLocForInst(RI, getOp1(I))); } - RI.Jit->SafeWriteRegToReg(EAX, ECX, Size, 0, regsInUse(RI)); + RI.Jit->SafeWriteRegToReg(EAX, ECX, Size, 0, regsInUse(RI), EmuCodeBlock::SAFE_LOADSTORE_NO_FASTMEM); if (RI.IInfo[I - RI.FirstI] & 4) regClearInst(RI, getOp1(I)); } @@ -1188,7 +1188,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) { Jit->MOV(32, R(EAX), loc1); } Jit->MOV(32, R(ECX), regLocForInst(RI, getOp2(I))); - RI.Jit->SafeWriteRegToReg(EAX, ECX, 32, 0, regsInUse(RI)); + RI.Jit->SafeWriteRegToReg(EAX, ECX, 32, 0, regsInUse(RI), EmuCodeBlock::SAFE_LOADSTORE_NO_FASTMEM); if (RI.IInfo[I - RI.FirstI] & 4) fregClearInst(RI, getOp1(I)); if (RI.IInfo[I - RI.FirstI] & 8) @@ -1251,12 +1251,12 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) { Jit->PSRLQ(XMM0, 32); Jit->MOVD_xmm(R(EAX), XMM0); Jit->MOV(32, R(ECX), address); - RI.Jit->SafeWriteRegToReg(EAX, ECX, 32, 0, regsInUse(RI)); + RI.Jit->SafeWriteRegToReg(EAX, ECX, 32, 0, regsInUse(RI), EmuCodeBlock::SAFE_LOADSTORE_NO_FASTMEM); Jit->MOVAPD(XMM0, value); Jit->MOVD_xmm(R(EAX), XMM0); Jit->MOV(32, R(ECX), address); - RI.Jit->SafeWriteRegToReg(EAX, ECX, 32, 4, regsInUse(RI)); + RI.Jit->SafeWriteRegToReg(EAX, ECX, 32, 4, regsInUse(RI), EmuCodeBlock::SAFE_LOADSTORE_NO_FASTMEM); Jit->SetJumpTarget(exit); if (RI.IInfo[I - RI.FirstI] & 4) diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp index 088336c43b..1518bc57bb 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.cpp @@ -3,6 +3,8 @@ // Refer to the license.txt file included. #include +#include +#include #include "Common.h" #include "../../HLE/HLE.h" @@ -217,14 +219,14 @@ namespace JitILProfiler const u64 totalElapsed = block.totalElapsed; const u64 numberOfCalls = block.numberOfCalls; const double elapsedPerCall = totalElapsed / (double)numberOfCalls; - fprintf(file.GetHandle(), "%016llx,%lld,%lld,%f\n", codeHash, totalElapsed, numberOfCalls, elapsedPerCall); + fprintf(file.GetHandle(), "%016" PRIx64 ",%" PRId64 ",%" PRId64 ",%f\n", codeHash, totalElapsed, numberOfCalls, elapsedPerCall); } } }; - std::auto_ptr finalizer; + std::unique_ptr finalizer; static void Init() { - finalizer = std::auto_ptr(new JitILProfilerFinalizer); + finalizer = std::unique_ptr(new JitILProfilerFinalizer); } static void Shutdown() { diff --git a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h index 8dfbcd522c..305a96015f 100644 --- a/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h +++ b/Source/Core/Core/Src/PowerPC/Jit64IL/JitIL.h @@ -58,14 +58,10 @@ private: JitBlockCache blocks; TrampolineCache trampolines; - // The default code buffer. We keep it around to not have to alloc/dealloc a - // large chunk of memory for each recompiled block. - PPCAnalyst::CodeBuffer code_buffer; - public: JitILAsmRoutineManager asm_routines; - JitIL() : code_buffer(32000) {} + JitIL() {} ~JitIL() {} // Initialization, etc @@ -140,6 +136,4 @@ public: void DynaRunTable63(UGeckoInstruction _inst) override; }; -void Jit(u32 em_address); - #endif // _JITIL_H diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp index 311ced730a..bc8272f48c 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitAsmCommon.cpp @@ -196,7 +196,7 @@ void CommonAsmRoutines::GenQuantizedStores() PACKSSDW(XMM0, R(XMM0)); PACKUSWB(XMM0, R(XMM0)); MOVD_xmm(R(EAX), XMM0); - SafeWriteRegToReg(AX, ECX, 16, 0, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_SWAP | SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(AX, ECX, 16, 0, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); @@ -215,7 +215,7 @@ void CommonAsmRoutines::GenQuantizedStores() PACKSSWB(XMM0, R(XMM0)); MOVD_xmm(R(EAX), XMM0); - SafeWriteRegToReg(AX, ECX, 16, 0, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_SWAP | SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(AX, ECX, 16, 0, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); @@ -241,7 +241,7 @@ void CommonAsmRoutines::GenQuantizedStores() MOV(16, R(AX), M((char*)psTemp + 4)); BSWAP(32, EAX); - SafeWriteRegToReg(EAX, ECX, 32, 0, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_SWAP | SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(EAX, ECX, 32, 0, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); @@ -261,7 +261,7 @@ void CommonAsmRoutines::GenQuantizedStores() MOVD_xmm(R(EAX), XMM0); BSWAP(32, EAX); ROL(32, R(EAX), Imm8(16)); - SafeWriteRegToReg(EAX, ECX, 32, 0, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_SWAP | SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(EAX, ECX, 32, 0, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); @@ -286,7 +286,7 @@ void CommonAsmRoutines::GenQuantizedSingleStores() // Easy! const u8* storeSingleFloat = AlignCode4(); - SafeWriteFloatToReg(XMM0, ECX, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteFloatToReg(XMM0, ECX, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); /* if (cpu_info.bSSSE3) { @@ -294,11 +294,11 @@ void CommonAsmRoutines::GenQuantizedSingleStores() // TODO: SafeWriteFloat MOVSS(M(&psTemp[0]), XMM0); MOV(32, R(EAX), M(&psTemp[0])); - SafeWriteRegToReg(EAX, ECX, 32, 0, SAFE_WRITE_NO_SWAP | SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(EAX, ECX, 32, 0, SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); } else { MOVSS(M(&psTemp[0]), XMM0); MOV(32, R(EAX), M(&psTemp[0])); - SafeWriteRegToReg(EAX, ECX, 32, 0, SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(EAX, ECX, 32, 0, SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); }*/ const u8* storeSingleU8 = AlignCode4(); // Used by MKWii @@ -309,7 +309,7 @@ void CommonAsmRoutines::GenQuantizedSingleStores() MAXSS(XMM0, R(XMM1)); MINSS(XMM0, M((void *)&m_255)); CVTTSS2SI(EAX, R(XMM0)); - SafeWriteRegToReg(AL, ECX, 8, 0, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(AL, ECX, 8, 0, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); const u8* storeSingleS8 = AlignCode4(); @@ -319,7 +319,7 @@ void CommonAsmRoutines::GenQuantizedSingleStores() MAXSS(XMM0, M((void *)&m_m128)); MINSS(XMM0, M((void *)&m_127)); CVTTSS2SI(EAX, R(XMM0)); - SafeWriteRegToReg(AL, ECX, 8, 0, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(AL, ECX, 8, 0, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); const u8* storeSingleU16 = AlignCode4(); // Used by MKWii @@ -330,7 +330,7 @@ void CommonAsmRoutines::GenQuantizedSingleStores() MAXSS(XMM0, R(XMM1)); MINSS(XMM0, M((void *)&m_65535)); CVTTSS2SI(EAX, R(XMM0)); - SafeWriteRegToReg(EAX, ECX, 16, 0, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(EAX, ECX, 16, 0, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); const u8* storeSingleS16 = AlignCode4(); @@ -340,7 +340,7 @@ void CommonAsmRoutines::GenQuantizedSingleStores() MAXSS(XMM0, M((void *)&m_m32768)); MINSS(XMM0, M((void *)&m_32767)); CVTTSS2SI(EAX, R(XMM0)); - SafeWriteRegToReg(EAX, ECX, 16, 0, QUANTIZED_REGS_TO_SAVE, SAFE_WRITE_NO_PROLOG | SAFE_WRITE_NO_FASTMEM); + SafeWriteRegToReg(EAX, ECX, 16, 0, QUANTIZED_REGS_TO_SAVE, SAFE_LOADSTORE_NO_PROLOG | SAFE_LOADSTORE_NO_FASTMEM); RET(); singleStoreQuantized = reinterpret_cast(const_cast(AlignCode16())); diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp index cd10306f2f..b7cc031c99 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/JitBackpatch.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #include "Common.h" #include "disasm.h" @@ -32,7 +33,7 @@ static void BackPatchError(const std::string &text, u8 *codePtr, u32 emAddress) #endif PanicAlert("%s\n\n" "Error encountered accessing emulated address %08x.\n" - "Culprit instruction: \n%s\nat %#llx", + "Culprit instruction: \n%s\nat %#" PRIx64, text.c_str(), emAddress, disbuf, code_addr); return; } @@ -233,7 +234,7 @@ const u8 *Jitx86Base::BackPatch(u8 *codePtr, u32 emAddress, void *ctx_void) XEmitter emitter(start); const u8 *trampoline = trampolines.GetWriteTrampoline(info, registersInUse); emitter.CALL((void *)trampoline); - emitter.NOP(codePtr + info.instructionSize - emitter.GetCodePtr()); + emitter.NOP((int)(codePtr + info.instructionSize - emitter.GetCodePtr())); return start; } #else diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp index ae62bae6ce..5c4a712024 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp +++ b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.cpp @@ -117,18 +117,20 @@ u8 *EmuCodeBlock::UnsafeLoadToReg(X64Reg reg_value, Gen::OpArg opAddress, int ac return result; } -void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress, int accessSize, s32 offset, u32 registersInUse, bool signExtend) +void EmuCodeBlock::SafeLoadToReg(X64Reg reg_value, const Gen::OpArg & opAddress, int accessSize, s32 offset, u32 registersInUse, bool signExtend, int flags) { if (!jit->js.memcheck) { registersInUse &= ~(1 << RAX | 1 << reg_value); } #if defined(_M_X64) + if (!Core::g_CoreStartupParameter.bMMU && + Core::g_CoreStartupParameter.bFastmem && + !(flags & (SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_FASTMEM)) #ifdef ENABLE_MEM_CHECK - if (!Core::g_CoreStartupParameter.bMMU && !Core::g_CoreStartupParameter.bEnableDebugging && Core::g_CoreStartupParameter.bFastmem) -#else - if (!Core::g_CoreStartupParameter.bMMU && Core::g_CoreStartupParameter.bFastmem) + && !Core::g_CoreStartupParameter.bEnableDebugging #endif + ) { u8 *mov = UnsafeLoadToReg(reg_value, opAddress, accessSize, offset, signExtend); @@ -282,14 +284,14 @@ void EmuCodeBlock::SafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int acce #if defined(_M_X64) if (!Core::g_CoreStartupParameter.bMMU && Core::g_CoreStartupParameter.bFastmem && - !(flags & (SAFE_WRITE_NO_SWAP | SAFE_WRITE_NO_FASTMEM)) + !(flags & (SAFE_LOADSTORE_NO_SWAP | SAFE_LOADSTORE_NO_FASTMEM)) #ifdef ENABLE_MEM_CHECK && !Core::g_CoreStartupParameter.bEnableDebugging #endif ) { MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write - u8 *mov = UnsafeWriteRegToReg(reg_value, reg_addr, accessSize, offset, !(flags & SAFE_WRITE_NO_SWAP)); + u8 *mov = UnsafeWriteRegToReg(reg_value, reg_addr, accessSize, offset, !(flags & SAFE_LOADSTORE_NO_SWAP)); if (accessSize == 8) { NOP(1); @@ -321,8 +323,8 @@ void EmuCodeBlock::SafeWriteRegToReg(X64Reg reg_value, X64Reg reg_addr, int acce MOV(32, M(&PC), Imm32(jit->js.compilerPC)); // Helps external systems know which instruction triggered the write TEST(32, R(reg_addr), Imm32(mem_mask)); FixupBranch fast = J_CC(CC_Z, true); - bool noProlog = flags & SAFE_WRITE_NO_PROLOG; - bool swap = !(flags & SAFE_WRITE_NO_SWAP); + bool noProlog = (0 != (flags & SAFE_LOADSTORE_NO_PROLOG)); + bool swap = !(flags & SAFE_LOADSTORE_NO_SWAP); ABI_PushRegistersAndAdjustStack(registersInUse, noProlog); switch (accessSize) { diff --git a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.h b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.h index 86802df822..a321ddd117 100644 --- a/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.h +++ b/Source/Core/Core/Src/PowerPC/JitCommon/Jit_Util.h @@ -28,13 +28,13 @@ public: // these return the address of the MOV, for backpatching u8 *UnsafeWriteRegToReg(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, int accessSize, s32 offset = 0, bool swap = true); u8 *UnsafeLoadToReg(Gen::X64Reg reg_value, Gen::OpArg opAddress, int accessSize, s32 offset, bool signExtend); - void SafeLoadToReg(Gen::X64Reg reg_value, const Gen::OpArg & opAddress, int accessSize, s32 offset, u32 registersInUse, bool signExtend); - enum SafeWriteFlags + enum SafeLoadStoreFlags { - SAFE_WRITE_NO_SWAP = 1, - SAFE_WRITE_NO_PROLOG = 2, - SAFE_WRITE_NO_FASTMEM = 4 + SAFE_LOADSTORE_NO_SWAP = 1, + SAFE_LOADSTORE_NO_PROLOG = 2, + SAFE_LOADSTORE_NO_FASTMEM = 4 }; + void SafeLoadToReg(Gen::X64Reg reg_value, const Gen::OpArg & opAddress, int accessSize, s32 offset, u32 registersInUse, bool signExtend, int flags = 0); void SafeWriteRegToReg(Gen::X64Reg reg_value, Gen::X64Reg reg_addr, int accessSize, s32 offset, u32 registersInUse, int flags = 0); // Trashes both inputs and EAX. diff --git a/Source/Core/Core/Src/PowerPC/JitILCommon/IR.cpp b/Source/Core/Core/Src/PowerPC/JitILCommon/IR.cpp index ffc5f94b62..3a4866f2f8 100644 --- a/Source/Core/Core/Src/PowerPC/JitILCommon/IR.cpp +++ b/Source/Core/Core/Src/PowerPC/JitILCommon/IR.cpp @@ -118,6 +118,7 @@ Fix profiled loads/stores to work safely. On 32-bit, one solution is to #include #include +#include #include #include #include "IR.h" @@ -1223,7 +1224,7 @@ struct Writer virtual ~Writer() {} }; -static std::auto_ptr writer; +static std::unique_ptr writer; static const std::string opcodeNames[] = { "Nop", "LoadGReg", "LoadLink", "LoadCR", "LoadCarry", "LoadCTR", @@ -1275,11 +1276,11 @@ void IRBuilder::WriteToFile(u64 codeHash) { _assert_(sizeof(opcodeNames) / sizeof(opcodeNames[0]) == Int3 + 1); if (!writer.get()) { - writer = std::auto_ptr(new Writer); + writer = std::unique_ptr(new Writer); } FILE* const file = writer->file.GetHandle(); - fprintf(file, "\ncode hash:%016llx\n", codeHash); + fprintf(file, "\ncode hash:%016" PRIx64 "\n", codeHash); const InstLoc lastCurReadPtr = curReadPtr; StartForwardPass(); diff --git a/Source/Core/Core/Src/PowerPC/JitInterface.cpp b/Source/Core/Core/Src/PowerPC/JitInterface.cpp index ce8cc2e3ef..91d43a7792 100644 --- a/Source/Core/Core/Src/PowerPC/JitInterface.cpp +++ b/Source/Core/Core/Src/PowerPC/JitInterface.cpp @@ -3,6 +3,7 @@ // Refer to the license.txt file included. #include +#include #ifdef _WIN32 #include @@ -171,12 +172,12 @@ namespace JitInterface double percent = 100.0 * (double)stat.cost / (double)cost_sum; #ifdef _WIN32 double timePercent = 100.0 * (double)block->ticCounter / (double)timecost_sum; - fprintf(f.GetHandle(), "%08x\t%s\t%llu\t%llu\t%.2lf\t%llf\t%lf\t%i\n", + fprintf(f.GetHandle(), "%08x\t%s\t%" PRIu64 "\t%" PRIu64 "\t%.2lf\t%llf\t%lf\t%i\n", block->originalAddress, name.c_str(), stat.cost, block->ticCounter, percent, timePercent, (double)block->ticCounter*1000.0/(double)countsPerSec, block->codeSize); #else - fprintf(f.GetHandle(), "%08x\t%s\t%llu\t???\t%.2lf\t???\t???\t%i\n", + fprintf(f.GetHandle(), "%08x\t%s\t%" PRIu64 "\t???\t%.2lf\t???\t???\t%i\n", block->originalAddress, name.c_str(), stat.cost, percent, block->codeSize); #endif } diff --git a/Source/Core/Core/Src/PowerPC/PPCTables.cpp b/Source/Core/Core/Src/PowerPC/PPCTables.cpp index 0041904a75..5854f1f0da 100644 --- a/Source/Core/Core/Src/PowerPC/PPCTables.cpp +++ b/Source/Core/Core/Src/PowerPC/PPCTables.cpp @@ -4,6 +4,7 @@ #include #include +#include #include "Common.h" #include "PPCTables.h" @@ -13,24 +14,15 @@ #include "Interpreter/Interpreter_Tables.h" #include "JitInterface.h" -struct op_inf -{ - const char *name; - int count; - bool operator < (const op_inf &o) const - { - return count > o.count; - } -}; - GekkoOPInfo *m_infoTable[64]; - GekkoOPInfo *m_infoTable4[1024]; - GekkoOPInfo *m_infoTable19[1024]; - GekkoOPInfo *m_infoTable31[1024]; - GekkoOPInfo *m_infoTable59[32]; - GekkoOPInfo *m_infoTable63[1024]; +GekkoOPInfo *m_infoTable[64]; +GekkoOPInfo *m_infoTable4[1024]; +GekkoOPInfo *m_infoTable19[1024]; +GekkoOPInfo *m_infoTable31[1024]; +GekkoOPInfo *m_infoTable59[32]; +GekkoOPInfo *m_infoTable63[1024]; - GekkoOPInfo *m_allInstructions[512]; - int m_numInstructions; +GekkoOPInfo *m_allInstructions[512]; +int m_numInstructions; GekkoOPInfo *GetOpInfo(UGeckoInstruction _inst) { @@ -181,26 +173,34 @@ void CountInstruction(UGeckoInstruction _inst) { GekkoOPInfo *info = GetOpInfo(_inst); if (info) + { info->runCount++; + } } void PrintInstructionRunCounts() { - std::vector temp; - for (int i = 0; i < m_numInstructions; i++) + typedef std::pair OpInfo; + std::vector temp; + temp.reserve(m_numInstructions); + for (int i = 0; i < m_numInstructions; ++i) { - op_inf x; - x.name = m_allInstructions[i]->opname; - x.count = m_allInstructions[i]->runCount; - temp.push_back(x); + GekkoOPInfo *pInst = m_allInstructions[i]; + temp.emplace_back(pInst->opname, pInst->runCount); } - std::sort(temp.begin(), temp.end()); - for (int i = 0; i < m_numInstructions; i++) + std::sort(temp.begin(), temp.end(), + [](const OpInfo &a, const OpInfo &b) + { + return a.second > b.second; + }); + + for (auto &inst : temp) { - if (temp[i].count == 0) + if (inst.second == 0) break; - DEBUG_LOG(POWERPC, "%s : %i", temp[i].name,temp[i].count); - //PanicAlert("%s : %i", temp[i].name,temp[i].count); + + DEBUG_LOG(POWERPC, "%s : %llu", inst.first, inst.second); + //PanicAlert("%s : %llu", inst.first, inst.second); } } @@ -211,20 +211,22 @@ void LogCompiledInstructions() File::IOFile f(StringFromFormat("%sinst_log%i.txt", File::GetUserPath(D_LOGS_IDX).c_str(), time), "w"); for (int i = 0; i < m_numInstructions; i++) { - if (m_allInstructions[i]->compileCount > 0) + GekkoOPInfo *pInst = m_allInstructions[i]; + if (pInst->compileCount > 0) { - fprintf(f.GetHandle(), "%s\t%i\t%lld\t%08x\n", m_allInstructions[i]->opname, - m_allInstructions[i]->compileCount, m_allInstructions[i]->runCount, m_allInstructions[i]->lastUse); + fprintf(f.GetHandle(), "%s\t%i\t%" PRId64 "\t%08x\n", pInst->opname, + pInst->compileCount, pInst->runCount, pInst->lastUse); } } f.Open(StringFromFormat("%sinst_not%i.txt", File::GetUserPath(D_LOGS_IDX).c_str(), time), "w"); for (int i = 0; i < m_numInstructions; i++) { - if (m_allInstructions[i]->compileCount == 0) + GekkoOPInfo *pInst = m_allInstructions[i]; + if (pInst->compileCount == 0) { - fprintf(f.GetHandle(), "%s\t%i\t%lld\n", m_allInstructions[i]->opname, - m_allInstructions[i]->compileCount, m_allInstructions[i]->runCount); + fprintf(f.GetHandle(), "%s\t%i\t%" PRId64 "\n", pInst->opname, + pInst->compileCount, pInst->runCount); } } diff --git a/Source/Core/Core/Src/State.cpp b/Source/Core/Core/Src/State.cpp index 99a1236123..f33003fdb1 100644 --- a/Source/Core/Core/Src/State.cpp +++ b/Source/Core/Core/Src/State.cpp @@ -247,7 +247,7 @@ void CompressAndDumpState(CompressAndDumpState_args save_args) // Setting up the header StateHeader header; memcpy(header.gameID, SConfig::GetInstance().m_LocalCoreStartupParameter.GetUniqueID().c_str(), 6); - header.size = g_use_compression ? buffer_size : 0; + header.size = g_use_compression ? (u32)buffer_size : 0; header.time = Common::Timer::GetDoubleTime(); f.WriteArray(&header, 1); @@ -261,9 +261,13 @@ void CompressAndDumpState(CompressAndDumpState_args save_args) lzo_uint out_len = 0; if ((i + IN_LEN) >= buffer_size) - cur_len = buffer_size - i; + { + cur_len = (lzo_uint32)(buffer_size - i); + } else + { cur_len = IN_LEN; + } if (lzo1x_1_compress(buffer_data + i, cur_len, out, &out_len, wrkmem) != LZO_E_OK) PanicAlertT("Internal LZO Error - compression failed"); diff --git a/Source/Core/DiscIO/Src/CompressedBlob.cpp b/Source/Core/DiscIO/Src/CompressedBlob.cpp index 3fdc779a44..c801ea3698 100644 --- a/Source/Core/DiscIO/Src/CompressedBlob.cpp +++ b/Source/Core/DiscIO/Src/CompressedBlob.cpp @@ -9,6 +9,8 @@ #include #endif +#include + #include "CompressedBlob.h" #include "DiscScrubber.h" #include "FileUtil.h" @@ -99,7 +101,7 @@ void CompressedBlobReader::GetBlock(u64 block_num, u8 *out_ptr) // First, check hash. u32 block_hash = HashAdler32(source, comp_block_size); if (block_hash != hashes[block_num]) - PanicAlert("Hash of block %lli is %08x instead of %08x.\n" + PanicAlert("Hash of block %" PRIu64 " is %08x instead of %08x.\n" "Your ISO, %s, is corrupt.", block_num, block_hash, hashes[block_num], file_name.c_str()); @@ -127,7 +129,7 @@ void CompressedBlobReader::GetBlock(u64 block_num, u8 *out_ptr) { // this seem to fire wrongly from time to time // to be sure, don't use compressed isos :P - PanicAlert("Failure reading block %lli - out of data and not at end.", block_num); + PanicAlert("Failure reading block %" PRIu64 " - out of data and not at end.", block_num); } inflateEnd(&z); if (uncomp_size != header.block_size) diff --git a/Source/Core/DiscIO/Src/DiscScrubber.cpp b/Source/Core/DiscIO/Src/DiscScrubber.cpp index 4f289cef9f..928383579e 100644 --- a/Source/Core/DiscIO/Src/DiscScrubber.cpp +++ b/Source/Core/DiscIO/Src/DiscScrubber.cpp @@ -7,6 +7,8 @@ #include "FileUtil.h" #include "DiscScrubber.h" +#include + namespace DiscIO { @@ -121,13 +123,13 @@ void GetNextBlock(File::IOFile& in, u8* buffer) if (m_isScrubbing && m_FreeTable[i]) { - DEBUG_LOG(DISCIO, "Freeing 0x%016llx", CurrentOffset); + DEBUG_LOG(DISCIO, "Freeing 0x%016" PRIx64, CurrentOffset); std::fill(buffer, buffer + m_BlockSize, 0xFF); in.Seek(m_BlockSize, SEEK_CUR); } else { - DEBUG_LOG(DISCIO, "Used 0x%016llx", CurrentOffset); + DEBUG_LOG(DISCIO, "Used 0x%016" PRIx64, CurrentOffset); in.ReadBytes(buffer, m_BlockSize); } @@ -150,7 +152,7 @@ void MarkAsUsed(u64 _Offset, u64 _Size) u64 CurrentOffset = _Offset; u64 EndOffset = CurrentOffset + _Size; - DEBUG_LOG(DISCIO, "Marking 0x%016llx - 0x%016llx as used", _Offset, EndOffset); + DEBUG_LOG(DISCIO, "Marking 0x%016" PRIx64 " - 0x%016" PRIx64 " as used", _Offset, EndOffset); while ((CurrentOffset < EndOffset) && (CurrentOffset < m_FileSize)) { diff --git a/Source/Core/DiscIO/Src/FileSystemGCWii.cpp b/Source/Core/DiscIO/Src/FileSystemGCWii.cpp index 90731b2573..cc09138f3e 100644 --- a/Source/Core/DiscIO/Src/FileSystemGCWii.cpp +++ b/Source/Core/DiscIO/Src/FileSystemGCWii.cpp @@ -8,6 +8,7 @@ #include #include #include +#include #include "FileSystemGCWii.h" #include "StringUtil.h" @@ -70,7 +71,7 @@ u64 CFileSystemGCWii::ReadFile(const char* _rFullPath, u8* _pBuffer, size_t _Max if (pFileInfo->m_FileSize > _MaxBufferSize) return 0; - DEBUG_LOG(DISCIO, "Filename: %s. Offset: %llx. Size: %llx",_rFullPath, + DEBUG_LOG(DISCIO, "Filename: %s. Offset: %" PRIx64 ". Size: %" PRIx64, _rFullPath, pFileInfo->m_Offset, pFileInfo->m_FileSize); m_rVolume->Read(pFileInfo->m_Offset, pFileInfo->m_FileSize, _pBuffer); diff --git a/Source/Core/DiscIO/Src/VolumeCreator.cpp b/Source/Core/DiscIO/Src/VolumeCreator.cpp index 7cf26f826a..4dd24f9b4b 100644 --- a/Source/Core/DiscIO/Src/VolumeCreator.cpp +++ b/Source/Core/DiscIO/Src/VolumeCreator.cpp @@ -183,8 +183,18 @@ static IVolume* CreateVolumeFromCryptedWiiImage(IBlobReader& _rReader, u32 _Part memset(IV, 0, 16); _rReader.Read(rPartition.Offset + 0x44c, 8, IV); + bool usingKoreanKey = false; + // Issue: 6813 + // Magic value is at 0x501f1 (1byte) + // If encrypted with the Korean key, the magic value would be 1 + // Otherwise it is zero + if (Korean && Reader.Read32(0x501ee) != 0) + { + usingKoreanKey = true; + } + aes_context AES_ctx; - aes_setkey_dec(&AES_ctx, (Korean ? g_MasterKeyK : g_MasterKey), 128); + aes_setkey_dec(&AES_ctx, (usingKoreanKey ? g_MasterKeyK : g_MasterKey), 128); u8 VolumeKey[16]; aes_crypt_cbc(&AES_ctx, AES_DECRYPT, 16, IV, SubKey, VolumeKey); diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.cpp b/Source/Core/DolphinWX/Src/GameListCtrl.cpp index c1d8ef3787..54c59dd806 100644 --- a/Source/Core/DolphinWX/Src/GameListCtrl.cpp +++ b/Source/Core/DolphinWX/Src/GameListCtrl.cpp @@ -9,6 +9,7 @@ #include #include +#include #include #include "FileSearch.h" @@ -383,7 +384,7 @@ wxString NiceSizeFormat(u64 _size) auto const value = (_size + unit_size / 2) / unit_size; auto const frac = (_size % unit_size * 10 + unit_size / 2) / unit_size % 10; - return StrToWxStr(StringFromFormat("%llu.%llu %s", value, frac, unit_symbols[unit])); + return StrToWxStr(StringFromFormat("%" PRIu64 ".%" PRIu64 " %s", value, frac, unit_symbols[unit])); } void CGameListCtrl::InsertItemInReportView(long _Index) diff --git a/Source/Core/DolphinWX/Src/ISOFile.cpp b/Source/Core/DolphinWX/Src/ISOFile.cpp index a867d9b6ca..5aa02f5df1 100644 --- a/Source/Core/DolphinWX/Src/ISOFile.cpp +++ b/Source/Core/DolphinWX/Src/ISOFile.cpp @@ -188,7 +188,7 @@ std::string GameListItem::CreateCacheFilename() // Filename.extension_HashOfFolderPath_Size.cache // Append hash to prevent ISO name-clashing in different folders. - Filename.append(StringFromFormat("%s_%x_%llx.cache", + Filename.append(StringFromFormat("%s_%x_%zx.cache", extension.c_str(), HashFletcher((const u8 *)LegalPathname.c_str(), LegalPathname.size()), File::GetSize(m_FileName))); diff --git a/Source/Core/DolphinWX/Src/ISOProperties.cpp b/Source/Core/DolphinWX/Src/ISOProperties.cpp index a191b79677..89f07815b1 100644 --- a/Source/Core/DolphinWX/Src/ISOProperties.cpp +++ b/Source/Core/DolphinWX/Src/ISOProperties.cpp @@ -7,6 +7,7 @@ #endif #include +#include #include "Common.h" #include "CommonPaths.h" @@ -118,7 +119,7 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW u8 _tTitleID[8]; if(OpenISO->GetTitleID(_tTitleID)) { - snprintf(tmp, 17, "%016llx", Common::swap64(_tTitleID)); + snprintf(tmp, 17, "%016" PRIx64, Common::swap64(_tTitleID)); _iniFilename = tmp; } } diff --git a/Source/Core/DolphinWX/Src/MainAndroid.cpp b/Source/Core/DolphinWX/Src/MainAndroid.cpp index 21bb84446b..1c1c481b24 100644 --- a/Source/Core/DolphinWX/Src/MainAndroid.cpp +++ b/Source/Core/DolphinWX/Src/MainAndroid.cpp @@ -278,10 +278,22 @@ JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetTitle( env->ReleaseStringUTFChars(jFile, File); return env->NewStringUTF(Name.c_str()); } + JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetVersionString(JNIEnv *env, jobject obj) { return env->NewStringUTF(scm_rev_str); } + +JNIEXPORT jboolean JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SupportsNEON(JNIEnv *env, jobject obj) +{ + return cpu_info.bNEON; +} + +JNIEXPORT void JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_SaveScreenShot(JNIEnv *env, jobject obj) +{ + Core::SaveScreenShot(); +} + JNIEXPORT jstring JNICALL Java_org_dolphinemu_dolphinemu_NativeLibrary_GetConfig(JNIEnv *env, jobject obj, jstring jFile, jstring jKey, jstring jValue, jstring jDefault) { IniFile ini; diff --git a/Source/Core/DolphinWX/Src/MemoryCards/WiiSaveCrypted.cpp b/Source/Core/DolphinWX/Src/MemoryCards/WiiSaveCrypted.cpp index 10cebc904e..2ccc236395 100644 --- a/Source/Core/DolphinWX/Src/MemoryCards/WiiSaveCrypted.cpp +++ b/Source/Core/DolphinWX/Src/MemoryCards/WiiSaveCrypted.cpp @@ -7,12 +7,14 @@ // Licensed under the terms of the GNU GPL, version 2 // http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt +#include +#include + #include "WiiSaveCrypted.h" #include "FileUtil.h" #include "MathUtil.h" #include "NandPaths.h" #include "FileUtil.h" -#include static Common::replace_v replacements; @@ -152,7 +154,7 @@ void CWiiSaveCrypted::ReadHDR() md5((u8*)&_header, HEADER_SZ, md5_calc); if (memcmp(md5_file, md5_calc, 0x10)) { - PanicAlertT("MD5 mismatch\n %016llx%016llx != %016llx%016llx", Common::swap64(md5_file),Common::swap64(md5_file+8), Common::swap64(md5_calc), Common::swap64(md5_calc+8)); + PanicAlertT("MD5 mismatch\n %016" PRIx64 "%016" PRIx64 " != %016" PRIx64 "%016" PRIx64, Common::swap64(md5_file),Common::swap64(md5_file+8), Common::swap64(md5_calc), Common::swap64(md5_calc+8)); b_valid= false; } @@ -244,7 +246,7 @@ void CWiiSaveCrypted::ReadBKHDR() if (_sizeOfFiles + FULL_CERT_SZ != _totalSize) WARN_LOG(CONSOLE, "Size(%x) + cert(%x) does not equal totalsize(%x)", _sizeOfFiles, FULL_CERT_SZ, _totalSize); if (m_TitleID != Common::swap64(bkhdr.SaveGameTitle)) - WARN_LOG(CONSOLE, "Encrypted title (%llx) does not match unencrypted title (%llx)", m_TitleID, Common::swap64(bkhdr.SaveGameTitle)); + WARN_LOG(CONSOLE, "Encrypted title (%" PRIx64 ") does not match unencrypted title (%" PRIx64 ")", m_TitleID, Common::swap64(bkhdr.SaveGameTitle)); } void CWiiSaveCrypted::WriteBKHDR() diff --git a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp index 86127eba6b..5e145ec391 100644 --- a/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp +++ b/Source/Core/DolphinWX/Src/WiimoteConfigDiag.cpp @@ -3,6 +3,7 @@ #include "HW/Wiimote.h" #include "HW/WiimoteReal/WiimoteReal.h" #include "Frame.h" +#include "NetPlayProto.h" WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin) : wxDialog(parent, -1, _("Dolphin Wiimote Configuration"), wxDefaultPosition, wxDefaultSize) @@ -134,6 +135,16 @@ WiimoteConfigDiag::WiimoteConfigDiag(wxWindow* const parent, InputPlugin& plugin WiimoteSpkVolumeText->Disable(); WiimoteSpkVolumeMinText->Disable(); WiimoteSpkVolumeMaxText->Disable(); + if (NetPlay::IsNetPlayRunning()) + { + bb_source->Disable(); + for (int i = 0; i < 4; ++i) + { + wiimote_label[i]->Disable(); + wiimote_source_ch[i]->Disable(); + } + } + } diff --git a/Source/Core/InputCommon/Src/ControllerInterface/SDL/SDL.cpp b/Source/Core/InputCommon/Src/ControllerInterface/SDL/SDL.cpp index bcd3586dc6..24e0d0de58 100644 --- a/Source/Core/InputCommon/Src/ControllerInterface/SDL/SDL.cpp +++ b/Source/Core/InputCommon/Src/ControllerInterface/SDL/SDL.cpp @@ -154,12 +154,13 @@ Joystick::~Joystick() { // stop/destroy all effects SDL_HapticStopAll(m_haptic); - std::list::iterator - i = m_state_out.begin(), - e = m_state_out.end(); - for ( ; i != e; ++i) - if (i->id != -1) - SDL_HapticDestroyEffect(m_haptic, i->id); + for (auto &i : m_state_out) + { + if (i.id != -1) + { + SDL_HapticDestroyEffect(m_haptic, i.id); + } + } // close haptic first SDL_HapticClose(m_haptic); } @@ -210,7 +211,7 @@ void Joystick::ConstantEffect::SetState(ControlState state) } const Sint16 old = m_effect.effect.constant.level; - m_effect.effect.constant.level = state * 0x7FFF; + m_effect.effect.constant.level = (Sint16)(state * 0x7FFF); if (old != m_effect.effect.constant.level) m_effect.changed = true; } @@ -228,7 +229,7 @@ void Joystick::RampEffect::SetState(ControlState state) } const Sint16 old = m_effect.effect.ramp.start; - m_effect.effect.ramp.start = state * 0x7FFF; + m_effect.effect.ramp.start = (Sint16)(state * 0x7FFF); if (old != m_effect.effect.ramp.start) m_effect.changed = true; } @@ -247,7 +248,7 @@ void Joystick::SineEffect::SetState(ControlState state) const Sint16 old = m_effect.effect.periodic.magnitude; m_effect.effect.periodic.period = 5; - m_effect.effect.periodic.magnitude = state * 0x5000; + m_effect.effect.periodic.magnitude = (Sint16)(state * 0x5000); m_effect.effect.periodic.attack_length = 0; m_effect.effect.periodic.fade_length = 500; @@ -293,7 +294,7 @@ void Joystick::TriangleEffect::SetState(ControlState state) const Sint16 old = m_effect.effect.periodic.magnitude; m_effect.effect.periodic.period = 5; - m_effect.effect.periodic.magnitude = state * 0x5000; + m_effect.effect.periodic.magnitude = (Sint16)(state * 0x5000); m_effect.effect.periodic.attack_length = 0; m_effect.effect.periodic.fade_length = 100; @@ -313,34 +314,35 @@ bool Joystick::UpdateInput() bool Joystick::UpdateOutput() { #ifdef USE_SDL_HAPTIC - std::list::iterator - i = m_state_out.begin(), - e = m_state_out.end(); - for ( ; i != e; ++i) + for (auto &i : m_state_out) { - if (i->changed) // if SetState was called on this output + if (i.changed) // if SetState was called on this output { - if (-1 == i->id) // effect isn't currently uploaded + if (-1 == i.id) // effect isn't currently uploaded { - if (i->effect.type) // if outputstate is >0 this would be true - if ((i->id = SDL_HapticNewEffect( m_haptic, &i->effect )) > -1) // upload the effect - SDL_HapticRunEffect(m_haptic, i->id, 1); // run the effect + if (i.effect.type) // if outputstate is >0 this would be true + { + if ((i.id = SDL_HapticNewEffect(m_haptic, &i.effect)) > -1) // upload the effect + { + SDL_HapticRunEffect(m_haptic, i.id, 1); // run the effect + } + } } else // effect is already uploaded { - if (i->effect.type) // if ouputstate >0 + if (i.effect.type) // if ouputstate >0 { - SDL_HapticUpdateEffect(m_haptic, i->id, &i->effect); // update the effect + SDL_HapticUpdateEffect(m_haptic, i.id, &i.effect); // update the effect } else { - SDL_HapticStopEffect(m_haptic, i->id); // else, stop and remove the effect - SDL_HapticDestroyEffect(m_haptic, i->id); - i->id = -1; // mark it as not uploaded + SDL_HapticStopEffect(m_haptic, i.id); // else, stop and remove the effect + SDL_HapticDestroyEffect(m_haptic, i.id); + i.id = -1; // mark it as not uploaded } } - i->changed = false; + i.changed = false; } } #endif diff --git a/Source/Core/VideoBackends/D3D/Src/PerfQuery.cpp b/Source/Core/VideoBackends/D3D/Src/PerfQuery.cpp index 1bcd314291..b2c77a876e 100644 --- a/Source/Core/VideoBackends/D3D/Src/PerfQuery.cpp +++ b/Source/Core/VideoBackends/D3D/Src/PerfQuery.cpp @@ -116,7 +116,7 @@ void PerfQuery::FlushOne() } // NOTE: Reported pixel metrics should be referenced to native resolution - m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight(); + m_results[entry.query_type] += (u32)(result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight()); m_query_read_pos = (m_query_read_pos + 1) % ArraySize(m_query_buffer); --m_query_count; @@ -147,7 +147,7 @@ void PerfQuery::WeakFlush() if (hr == S_OK) { // NOTE: Reported pixel metrics should be referenced to native resolution - m_results[entry.query_type] += (u64)result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight(); + m_results[entry.query_type] += (u32)(result * EFB_WIDTH / g_renderer->GetTargetWidth() * EFB_HEIGHT / g_renderer->GetTargetHeight()); m_query_read_pos = (m_query_read_pos + 1) % ArraySize(m_query_buffer); --m_query_count; diff --git a/Source/Core/VideoBackends/D3D/Src/Render.cpp b/Source/Core/VideoBackends/D3D/Src/Render.cpp index 9790f2b52e..d2938e6600 100644 --- a/Source/Core/VideoBackends/D3D/Src/Render.cpp +++ b/Source/Core/VideoBackends/D3D/Src/Render.cpp @@ -2,7 +2,8 @@ // Licensed under GPLv2 // Refer to the license.txt file included. -#include +#include +#include #include "Timer.h" @@ -33,6 +34,7 @@ #include "FPSCounter.h" #include "ConfigManager.h" #include +#include "ImageWrite.h" namespace DX11 { @@ -680,7 +682,7 @@ void Renderer::SetBlendMode(bool forceUpdate) } } -void Renderer::TakeScreenshot(const TargetRectangle &rc, std::string filename) +bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle& rc) { if (!s_screenshot_texture) CreateScreenshotTexture(rc); @@ -689,26 +691,25 @@ void Renderer::TakeScreenshot(const TargetRectangle &rc, std::string filename) D3D11_BOX box = CD3D11_BOX(rc.left, rc.top, 0, rc.right, rc.bottom, 1); D3D::context->CopySubresourceRegion(s_screenshot_texture, 0, 0, 0, 0, (ID3D11Resource*)D3D::GetBackBuffer()->GetTex(), 0, &box); - u8* __restrict dest = (u8*) malloc(rc.GetWidth() * rc.GetHeight() * 3); - D3D11_MAPPED_SUBRESOURCE map; D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ_WRITE, 0, &map); - u8* src = (u8*) map.pData; - for (int y = 0; y < rc.GetHeight(); ++y) - { - u8* __restrict row = src; - for (int x = 0; x < rc.GetWidth(); ++x) - { - *dest++ = *row++; - *dest++ = *row++; - *dest++ = *row++; - row++; - } - src += map.RowPitch; - } + + bool saved_png = TextureToPng((u8*)map.pData, map.RowPitch, filename, rc.GetWidth(), rc.GetHeight(), false); + D3D::context->Unmap(s_screenshot_texture, 0); - SaveScreenshot(dest, rc.GetWidth(), rc.GetHeight(), filename); + + if (saved_png) + { + OSD::AddMessage(StringFromFormat("Saved %i x %i %s", rc.GetWidth(), + rc.GetHeight(), filename.c_str())); + } + else + { + OSD::AddMessage(StringFromFormat("Error saving %s", filename.c_str())); + } + + return saved_png; } void formatBufferDump(const u8* in, u8* out, int w, int h, int p) @@ -846,7 +847,7 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r // done with drawing the game stuff, good moment to save a screenshot if (s_bScreenshot) { - TakeScreenshot(GetTargetRectangle(), s_sScreenshotName); + SaveScreenshot(s_sScreenshotName, GetTargetRectangle()); s_bScreenshot = false; } @@ -921,7 +922,7 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r if (SConfig::GetInstance().m_ShowLag) { char lag[10]; - StringCchPrintfA(lag, 10, "Lag: %llu\n", Movie::g_currentLagCount); + StringCchPrintfA(lag, 10, "Lag: %" PRIu64 "\n", Movie::g_currentLagCount); D3D::font.DrawTextScaled(0, 18, 20, 0.0f, 0xFF00FFFF, lag); } diff --git a/Source/Core/VideoBackends/D3D/Src/Render.h b/Source/Core/VideoBackends/D3D/Src/Render.h index e899484111..12e5b595d3 100644 --- a/Source/Core/VideoBackends/D3D/Src/Render.h +++ b/Source/Core/VideoBackends/D3D/Src/Render.h @@ -48,10 +48,9 @@ public: void UpdateViewport(); - static void TakeScreenshot(const TargetRectangle &rc, std::string filename); + bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc); static bool CheckForResize(); - }; } diff --git a/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp b/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp index 7ee92459c6..22e644b2d8 100644 --- a/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp +++ b/Source/Core/VideoBackends/D3D/Src/TextureCache.cpp @@ -14,6 +14,7 @@ #include "PSTextureEncoder.h" #include "HW/Memmap.h" #include "VideoConfig.h" +#include "ImageWrite.h" namespace DX11 { @@ -32,7 +33,7 @@ void TextureCache::TCacheEntry::Bind(unsigned int stage) D3D::context->PSSetShaderResources(stage, 1, &texture->GetSRV()); } -bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) +bool TextureCache::TCacheEntry::Save(const std::string filename, unsigned int level) { // TODO: Somehow implement this (D3DX11 doesn't support dumping individual LODs) static bool warn_once = true; @@ -42,8 +43,35 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) warn_once = false; return false; } - //return SUCCEEDED(PD3DX11SaveTextureToFileA(D3D::context, texture->GetTex(), D3DX11_IFF_PNG, filename)); - return true; + + ID3D11Texture2D* pNewTexture = NULL; + ID3D11Texture2D* pSurface = texture->GetTex(); + D3D11_TEXTURE2D_DESC desc; + pSurface->GetDesc(&desc); + + desc.BindFlags = 0; + desc.CPUAccessFlags = D3D11_CPU_ACCESS_READ | D3D11_CPU_ACCESS_WRITE; + desc.Usage = D3D11_USAGE_STAGING; + + HRESULT hr = D3D::device->CreateTexture2D(&desc, NULL, &pNewTexture); + + bool saved_png = false; + + if (SUCCEEDED(hr) && pNewTexture) + { + D3D::context->CopyResource(pNewTexture, pSurface); + + D3D11_MAPPED_SUBRESOURCE map; + HRESULT hr = D3D::context->Map(pNewTexture, 0, D3D11_MAP_READ_WRITE, 0, &map); + if (SUCCEEDED(hr)) + { + saved_png = TextureToPng((u8*)map.pData, map.RowPitch, filename, desc.Width, desc.Height); + D3D::context->Unmap(pNewTexture, 0); + } + SAFE_RELEASE(pNewTexture); + } + + return saved_png; } void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height, diff --git a/Source/Core/VideoBackends/D3D/Src/TextureCache.h b/Source/Core/VideoBackends/D3D/Src/TextureCache.h index 94adfe8cce..91603bc56d 100644 --- a/Source/Core/VideoBackends/D3D/Src/TextureCache.h +++ b/Source/Core/VideoBackends/D3D/Src/TextureCache.h @@ -36,7 +36,7 @@ private: const float *colmat); void Bind(unsigned int stage); - bool Save(const char filename[], unsigned int level); + bool Save(const std::string filename, unsigned int level); }; TCacheEntryBase* CreateTexture(unsigned int width, unsigned int height, diff --git a/Source/Core/VideoBackends/D3D/Src/VertexManager.cpp b/Source/Core/VideoBackends/D3D/Src/VertexManager.cpp index a48a3d289a..b951a7464f 100644 --- a/Source/Core/VideoBackends/D3D/Src/VertexManager.cpp +++ b/Source/Core/VideoBackends/D3D/Src/VertexManager.cpp @@ -222,9 +222,9 @@ void VertexManager::vFlush() tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1, tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, tex.texTlut[i&3].tlut_format, - (tex.texMode0[i&3].min_filter & 3), + ((tex.texMode0[i&3].min_filter & 3) != 0), (tex.texMode1[i&3].max_lod + 0xf) / 0x10, - tex.texImage1[i&3].image_type); + (tex.texImage1[i&3].image_type != 0)); if (tentry) { diff --git a/Source/Core/VideoBackends/OGL/Src/RasterFont.cpp b/Source/Core/VideoBackends/OGL/Src/RasterFont.cpp index c1817f3eeb..42b8963784 100644 --- a/Source/Core/VideoBackends/OGL/Src/RasterFont.cpp +++ b/Source/Core/VideoBackends/OGL/Src/RasterFont.cpp @@ -144,7 +144,7 @@ RasterFont::RasterFont() for(u32 y=0; y #include #include +#include #include "GLUtil.h" +#if defined(HAVE_WX) && HAVE_WX +#include "WxUtils.h" +#endif #include "FileUtil.h" @@ -22,6 +26,7 @@ #include "DriverDetails.h" #include "VideoConfig.h" #include "Statistics.h" +#include "ImageWrite.h" #include "PixelEngine.h" #include "Render.h" #include "BPStructs.h" @@ -69,7 +74,6 @@ void VideoConfig::UpdateProjectionHack() ::UpdateProjectionHack(g_Config.iPhackvalue, g_Config.sPhackvalue); } - int OSDInternalW, OSDInternalH; namespace OGL @@ -108,6 +112,10 @@ static u32 s_blendMode; static bool s_vsync; +#if defined(HAVE_WX) && HAVE_WX +static std::thread scrshotThread; +#endif + // EFB cache related static const u32 EFB_CACHE_RECT_SIZE = 64; // Cache 64x64 blocks. static const u32 EFB_CACHE_WIDTH = (EFB_WIDTH + EFB_CACHE_RECT_SIZE - 1) / EFB_CACHE_RECT_SIZE; // round up @@ -461,19 +469,23 @@ Renderer::Renderer() } - g_Config.backend_info.bSupportsDualSourceBlend = GLEW_ARB_blend_func_extended; - g_Config.backend_info.bSupportsGLSLUBO = GLEW_ARB_uniform_buffer_object; - g_Config.backend_info.bSupportsPrimitiveRestart = GLEW_VERSION_3_1 || GLEW_NV_primitive_restart; - g_Config.backend_info.bSupportsEarlyZ = GLEW_ARB_shader_image_load_store; +#define TO_BOOL(c) (0 != (c)) - g_ogl_config.bSupportsGLSLCache = GLEW_ARB_get_program_binary; - g_ogl_config.bSupportsGLPinnedMemory = GLEW_AMD_pinned_memory; - g_ogl_config.bSupportsGLSync = GLEW_ARB_sync; - g_ogl_config.bSupportsGLBaseVertex = GLEW_ARB_draw_elements_base_vertex; - g_ogl_config.bSupportCoverageMSAA = GLEW_NV_framebuffer_multisample_coverage; - g_ogl_config.bSupportSampleShading = GLEW_ARB_sample_shading; - g_ogl_config.bSupportOGL31 = GLEW_VERSION_3_1; - g_ogl_config.bSupportViewportFloat = GLEW_ARB_viewport_array; + g_Config.backend_info.bSupportsDualSourceBlend = TO_BOOL(GLEW_ARB_blend_func_extended); + g_Config.backend_info.bSupportsGLSLUBO = TO_BOOL(GLEW_ARB_uniform_buffer_object); + g_Config.backend_info.bSupportsPrimitiveRestart = TO_BOOL(GLEW_VERSION_3_1) || TO_BOOL(GLEW_NV_primitive_restart); + g_Config.backend_info.bSupportsEarlyZ = TO_BOOL(GLEW_ARB_shader_image_load_store); + + g_ogl_config.bSupportsGLSLCache = TO_BOOL(GLEW_ARB_get_program_binary); + g_ogl_config.bSupportsGLPinnedMemory = TO_BOOL(GLEW_AMD_pinned_memory); + g_ogl_config.bSupportsGLSync = TO_BOOL(GLEW_ARB_sync); + g_ogl_config.bSupportsGLBaseVertex = TO_BOOL(GLEW_ARB_draw_elements_base_vertex); + g_ogl_config.bSupportCoverageMSAA = TO_BOOL(GLEW_NV_framebuffer_multisample_coverage); + g_ogl_config.bSupportSampleShading = TO_BOOL(GLEW_ARB_sample_shading); + g_ogl_config.bSupportOGL31 = TO_BOOL(GLEW_VERSION_3_1); + g_ogl_config.bSupportViewportFloat = TO_BOOL(GLEW_ARB_viewport_array); + +#undef TO_BOOL if(strstr(g_ogl_config.glsl_version, "1.00") || strstr(g_ogl_config.glsl_version, "1.10") || strstr(g_ogl_config.glsl_version, "1.20")) { @@ -616,6 +628,11 @@ Renderer::Renderer() Renderer::~Renderer() { + +#if defined(HAVE_WX) && HAVE_WX + if (scrshotThread.joinable()) + scrshotThread.join(); +#endif } void Renderer::Shutdown() @@ -681,7 +698,7 @@ void Renderer::DrawDebugInfo() p+=sprintf(p, "FPS: %d\n", s_fps); if (SConfig::GetInstance().m_ShowLag) - p+=sprintf(p, "Lag: %llu\n", Movie::g_currentLagCount); + p+=sprintf(p, "Lag: %" PRIu64 "\n", Movie::g_currentLagCount); if (g_ActiveConfig.bShowInputDisplay) p+=sprintf(p, "%s", Movie::GetInputDisplay().c_str()); @@ -1391,9 +1408,11 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r // Save screenshot if (s_bScreenshot) { - TakeScreenshot(flipped_trc, s_sScreenshotName); - s_bScreenshot = false; + std::lock_guard lk(s_criticalScreenshot); + SaveScreenshot(s_sScreenshotName, flipped_trc); // Reset settings + s_sScreenshotName.clear(); + s_bScreenshot = false; } // Frame dumps are handled a little differently in Windows @@ -1608,7 +1627,7 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r // For testing zbuffer targets. // Renderer::SetZBufferRender(); - // SaveTexture("tex.tga", GL_TEXTURE_2D, s_FakeZTarget, + // SaveTexture("tex.png", GL_TEXTURE_2D, s_FakeZTarget, // GetTargetWidth(), GetTargetHeight()); Core::Callback_VideoCopiedToXFB(XFBWrited || (g_ActiveConfig.bUseXFB && g_ActiveConfig.bUseRealXFB)); XFBWrited = false; @@ -1769,44 +1788,48 @@ void Renderer::SetInterlacingMode() // TODO } -void Renderer::FlipImageData(u8 *data, int w, int h) +void Renderer::FlipImageData(u8 *data, int w, int h, int pixel_width) { - // XXX make this faster - u8* __restrict top = data; - u8* bot = data + w * h * 3; - for (int y = 0; y < h / 2; y++) + // Flip image upside down. Damn OpenGL. + for (int y = 0; y < h / 2; ++y) { - size_t stride = w * 3; - bot -= stride; - u8* __restrict brow = bot; - for(size_t x = 0; x < stride; x++) + for(int x = 0; x < w; ++x) { - std::swap(*top++, *brow++); + for (auto delta = 0; delta < pixel_width; ++delta) + std::swap(data[(y * w + x) * pixel_width + delta], data[((h - 1 - y) * w + x) * pixel_width + delta]); } } } -void Renderer::TakeScreenshot(const TargetRectangle &back_rc, std::string filename) +} + +namespace OGL +{ + +bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle &back_rc) { u32 W = back_rc.GetWidth(); u32 H = back_rc.GetHeight(); - u8 *data = (u8 *)malloc((sizeof(u8) * 3 * W * H)); + u8 *data = new u8[W * 4 * H]; glPixelStorei(GL_PACK_ALIGNMENT, 1); - glReadPixels(back_rc.left, back_rc.bottom, W, H, GL_RGB, GL_UNSIGNED_BYTE, data); + glReadPixels(back_rc.left, back_rc.bottom, W, H, GL_RGBA, GL_UNSIGNED_BYTE, data); // Show failure message if (GL_REPORT_ERROR() != GL_NO_ERROR) { - free(data); + delete[] data; OSD::AddMessage("Error capturing or saving screenshot.", 2000); - return; + return false; } // Turn image upside down - FlipImageData(data, W, H); + FlipImageData(data, W, H, 4); + bool success = TextureToPng(data, W*4, filename, W, H, false); + delete[] data; + + return success; - SaveScreenshot(data, W, H, filename); } } diff --git a/Source/Core/VideoBackends/OGL/Src/Render.h b/Source/Core/VideoBackends/OGL/Src/Render.h index f38c9b4c58..0cda2f4c0e 100644 --- a/Source/Core/VideoBackends/OGL/Src/Render.h +++ b/Source/Core/VideoBackends/OGL/Src/Render.h @@ -63,7 +63,7 @@ public: void RenderText(const char* pstr, int left, int top, u32 color) override; void DrawDebugInfo(); - static void FlipImageData(u8 *data, int w, int h); + void FlipImageData(u8 *data, int w, int h, int pixel_width = 3); u32 AccessEFB(EFBAccessType type, u32 x, u32 y, u32 poke_data) override; @@ -80,7 +80,7 @@ public: void UpdateViewport() override; - static void TakeScreenshot(const TargetRectangle &rc, std::string filename); + bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc); private: void UpdateEFBCache(EFBAccessType type, u32 cacheRectIdx, const EFBRectangle& efbPixelRc, const TargetRectangle& targetPixelRc, const u32* data); diff --git a/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp b/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp index 9826033098..15135f3621 100644 --- a/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp +++ b/Source/Core/VideoBackends/OGL/Src/StreamBuffer.cpp @@ -59,7 +59,7 @@ StreamBuffer::~StreamBuffer() glDeleteBuffers(1, &m_buffer); } -#define SLOT(x) (x)*SYNC_POINTS/m_size +#define SLOT(x) ((x)*SYNC_POINTS/m_size) void StreamBuffer::Alloc ( size_t size, u32 stride ) { @@ -81,14 +81,14 @@ void StreamBuffer::Alloc ( size_t size, u32 stride ) case PINNED_MEMORY: // insert waiting slots for used memory - for(u32 i=SLOT(m_used_iterator); i= m_size) { // insert waiting slots in unused space at the end of the buffer - for(u32 i=SLOT(m_used_iterator); i < SYNC_POINTS; i++) + for (size_t i = SLOT(m_used_iterator); i < SYNC_POINTS; i++) + { fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0); + } // move to the start m_used_iterator = m_iterator_aligned = m_iterator = 0; // offset 0 is always aligned @@ -244,10 +246,14 @@ void StreamBuffer::Shutdown() void StreamBuffer::DeleteFences() { - for(u32 i=SLOT(m_free_iterator)+1; i < SYNC_POINTS; i++) + for (size_t i = SLOT(m_free_iterator) + 1; i < SYNC_POINTS; i++) + { glDeleteSync(fences[i]); - for(u32 i=0; i s_VBO; -bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level) +bool SaveTexture(const std::string filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level) { #ifndef USE_GLES3 int width = std::max(virtual_width >> level, 1); int height = std::max(virtual_height >> level, 1); - std::vector data(width * height); + u8* data = new u8[width * height * 4]; glActiveTexture(GL_TEXTURE0+9); glBindTexture(textarget, tex); - glGetTexImage(textarget, level, GL_BGRA, GL_UNSIGNED_BYTE, &data[0]); + glGetTexImage(textarget, level, GL_RGBA, GL_UNSIGNED_BYTE, data); glBindTexture(textarget, 0); TextureCache::SetStage(); @@ -75,10 +75,12 @@ bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width if (GL_NO_ERROR != err) { PanicAlert("Can't save texture, GL Error: %s", gluErrorString(err)); + delete[] data; return false; } - - return SaveTGA(filename, width, height, &data[0]); + bool success = TextureToPng(data, width * 4, filename, width, height, true); + delete[] data; + return success; #else return false; #endif @@ -125,13 +127,9 @@ void TextureCache::TCacheEntry::Bind(unsigned int stage) } } -bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level) +bool TextureCache::TCacheEntry::Save(const std::string filename, unsigned int level) { - // TODO: make ogl dump PNGs - std::string tga_filename(filename); - tga_filename.replace(tga_filename.size() - 3, 3, "tga"); - - return SaveTexture(tga_filename.c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height, level); + return SaveTexture(filename, GL_TEXTURE_2D, texture, virtual_width, virtual_height, level); } TextureCache::TCacheEntryBase* TextureCache::CreateTexture(unsigned int width, @@ -395,8 +393,8 @@ void TextureCache::TCacheEntry::FromRenderTarget(u32 dstAddr, unsigned int dstFo if (g_ActiveConfig.bDumpEFBTarget) { static int count = 0; - SaveTexture(StringFromFormat("%sefb_frame_%i.tga", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), - count++).c_str(), GL_TEXTURE_2D, texture, virtual_width, virtual_height, 0); + SaveTexture(StringFromFormat("%sefb_frame_%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), + count++), GL_TEXTURE_2D, texture, virtual_width, virtual_height, 0); } g_renderer->RestoreAPIState(); diff --git a/Source/Core/VideoBackends/OGL/Src/TextureCache.h b/Source/Core/VideoBackends/OGL/Src/TextureCache.h index 1c95d35f98..af1b60bc06 100644 --- a/Source/Core/VideoBackends/OGL/Src/TextureCache.h +++ b/Source/Core/VideoBackends/OGL/Src/TextureCache.h @@ -53,7 +53,7 @@ private: const float *colmat) override; void Bind(unsigned int stage) override; - bool Save(const char filename[], unsigned int level); + bool Save(const std::string filename, unsigned int level); }; ~TextureCache(); @@ -64,7 +64,7 @@ private: TCacheEntryBase* CreateRenderTargetTexture(unsigned int scaled_tex_w, unsigned int scaled_tex_h) override; }; -bool SaveTexture(const char* filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level); +bool SaveTexture(const std::string filename, u32 textarget, u32 tex, int virtual_width, int virtual_height, unsigned int level); } diff --git a/Source/Core/VideoBackends/OGL/Src/VertexManager.cpp b/Source/Core/VideoBackends/OGL/Src/VertexManager.cpp index 4fb355d897..1ff9b53e28 100644 --- a/Source/Core/VideoBackends/OGL/Src/VertexManager.cpp +++ b/Source/Core/VideoBackends/OGL/Src/VertexManager.cpp @@ -43,8 +43,8 @@ const u32 MAX_VBUFFER_SIZE = 16*1024*1024; static StreamBuffer *s_vertexBuffer; static StreamBuffer *s_indexBuffer; -static u32 s_baseVertex; -static u32 s_offset[3]; +static size_t s_baseVertex; +static size_t s_offset[3]; VertexManager::VertexManager() { @@ -89,7 +89,7 @@ void VertexManager::PrepareDrawBuffers(u32 stride) u32 index_size = (triangle_index_size+line_index_size+point_index_size) * sizeof(u16); s_vertexBuffer->Alloc(vertex_data_size, stride); - u32 offset = s_vertexBuffer->Upload(GetVertexBuffer(), vertex_data_size); + size_t offset = s_vertexBuffer->Upload(GetVertexBuffer(), vertex_data_size); s_baseVertex = offset / stride; s_indexBuffer->Alloc(index_size); @@ -121,17 +121,17 @@ void VertexManager::Draw(u32 stride) if(g_ogl_config.bSupportsGLBaseVertex) { if (triangle_index_size > 0) { - glDrawRangeElementsBaseVertex(triangle_mode, 0, max_index, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0], s_baseVertex); + glDrawRangeElementsBaseVertex(triangle_mode, 0, max_index, triangle_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[0], (GLint)s_baseVertex); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } if (line_index_size > 0) { - glDrawRangeElementsBaseVertex(GL_LINES, 0, max_index, line_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[1], s_baseVertex); + glDrawRangeElementsBaseVertex(GL_LINES, 0, max_index, line_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[1], (GLint)s_baseVertex); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } if (point_index_size > 0) { - glDrawRangeElementsBaseVertex(GL_POINTS, 0, max_index, point_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[2], s_baseVertex); + glDrawRangeElementsBaseVertex(GL_POINTS, 0, max_index, point_index_size, GL_UNSIGNED_SHORT, (u8*)NULL+s_offset[2], (GLint)s_baseVertex); INCSTAT(stats.thisFrame.numIndexedDrawCalls); } } @@ -236,9 +236,9 @@ void VertexManager::vFlush() tex.texImage0[i&3].width + 1, tex.texImage0[i&3].height + 1, tex.texImage0[i&3].format, tex.texTlut[i&3].tmem_offset<<9, tex.texTlut[i&3].tlut_format, - (tex.texMode0[i&3].min_filter & 3), + (0 != (tex.texMode0[i&3].min_filter & 3)), (tex.texMode1[i&3].max_lod + 0xf) / 0x10, - tex.texImage1[i&3].image_type); + (0 != tex.texImage1[i&3].image_type)); if (tentry) { @@ -335,13 +335,13 @@ void VertexManager::vFlush() if (g_ActiveConfig.iLog & CONF_SAVETARGETS) { char str[128]; - sprintf(str, "%starg%.3d.tga", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId); + sprintf(str, "%starg%.3d.png", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), g_ActiveConfig.iSaveTargetId); TargetRectangle tr; tr.left = 0; tr.right = Renderer::GetTargetWidth(); tr.top = 0; tr.bottom = Renderer::GetTargetHeight(); - Renderer::TakeScreenshot(tr, str); + g_renderer->SaveScreenshot(str, tr); } #endif g_Config.iSaveTargetId++; diff --git a/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp b/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp index 4472639a20..75c6c08ada 100644 --- a/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp +++ b/Source/Core/VideoBackends/Software/Src/DebugUtil.cpp @@ -42,7 +42,7 @@ void Init() } } -void SaveTexture(const char* filename, u32 texmap, s32 mip) +void SaveTexture(const std::string filename, u32 texmap, s32 mip) { FourTexUnits& texUnit = bpmem.tex[(texmap >> 2) & 1]; u8 subTexmap = texmap & 3; @@ -54,28 +54,21 @@ void SaveTexture(const char* filename, u32 texmap, s32 mip) u8 *data = new u8[width * height * 4]; - GetTextureBGRA(data, texmap, mip, width, height); + GetTextureRGBA(data, texmap, mip, width, height); - (void)SaveTGA(filename, width, height, data); + (void)TextureToPng(data, width*4, filename, width, height, true); + delete[] data; - delete []data; } -void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height) +void GetTextureRGBA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height) { - u8 sample[4]; - for (u32 y = 0; y < height; y++) { for (u32 x = 0; x < width; x++) { - TextureSampler::SampleMip(x << 7, y << 7, mip, false, texmap, sample); - - // RGBA to BGRA - *(dst++) = sample[2]; - *(dst++) = sample[1]; - *(dst++) = sample[0]; - *(dst++) = sample[3]; + TextureSampler::SampleMip(x << 7, y << 7, mip, false, texmap, dst); + dst += 4; } } } @@ -104,9 +97,9 @@ void DumpActiveTextures() s32 maxLod = GetMaxTextureLod(texmap); for (s32 mip = 0; mip <= maxLod; ++mip) { - SaveTexture(StringFromFormat("%star%i_ind%i_map%i_mip%i.tga", + SaveTexture(StringFromFormat("%star%i_ind%i_map%i_mip%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), - swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip); + swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip), texmap, mip); } } @@ -121,14 +114,14 @@ void DumpActiveTextures() s32 maxLod = GetMaxTextureLod(texmap); for (s32 mip = 0; mip <= maxLod; ++mip) { - SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.tga", + SaveTexture(StringFromFormat("%star%i_stage%i_map%i_mip%i.png", File::GetUserPath(D_DUMPTEXTURES_IDX).c_str(), - swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip).c_str(), texmap, mip); + swstats.thisFrame.numDrawnObjects, stageNum, texmap, mip), texmap, mip); } } } -void DumpEfb(const char* filename) +void DumpEfb(const std::string filename) { u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4]; u8 *writePtr = data; @@ -139,20 +132,19 @@ void DumpEfb(const char* filename) for (int x = 0; x < EFB_WIDTH; x++) { EfbInterface::GetColor(x, y, sample); - // ABGR to BGRA - *(writePtr++) = sample[1]; - *(writePtr++) = sample[2]; + // ABGR to RGBA *(writePtr++) = sample[3]; + *(writePtr++) = sample[2]; + *(writePtr++) = sample[1]; *(writePtr++) = sample[0]; } } - (void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data); - - delete []data; + (void)TextureToPng(data, EFB_WIDTH * 4, filename, EFB_WIDTH, EFB_HEIGHT, true); + delete[] data; } -void DumpDepth(const char* filename) +void DumpDepth(const std::string filename) { u8 *data = new u8[EFB_WIDTH * EFB_HEIGHT * 4]; u8 *writePtr = data; @@ -162,17 +154,16 @@ void DumpDepth(const char* filename) for (int x = 0; x < EFB_WIDTH; x++) { u32 depth = EfbInterface::GetDepth(x, y); - // depth to bgra - *(writePtr++) = (depth >> 16) & 0xff; + // depth to rgba + *(writePtr++) = depth & 0xff; *(writePtr++) = (depth >> 8) & 0xff; - *(writePtr++) = depth & 0xff; + *(writePtr++) = (depth >> 16) & 0xff; *(writePtr++) = 255; } } - (void)SaveTGA(filename, EFB_WIDTH, EFB_HEIGHT, data); - - delete []data; + (void)TextureToPng(data, EFB_WIDTH * 4, filename, EFB_WIDTH, EFB_HEIGHT, true); + delete[] data; } void DrawObjectBuffer(s16 x, s16 y, u8 *color, int bufferBase, int subBuffer, const char *name) @@ -232,9 +223,9 @@ void OnObjectEnd() if (!g_bSkipCurrentFrame) { if (g_SWVideoConfig.bDumpObjects && swstats.thisFrame.numDrawnObjects >= g_SWVideoConfig.drawStart && swstats.thisFrame.numDrawnObjects < g_SWVideoConfig.drawEnd) - DumpEfb(StringFromFormat("%sobject%i.tga", + DumpEfb(StringFromFormat("%sobject%i.png", File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), - swstats.thisFrame.numDrawnObjects).c_str()); + swstats.thisFrame.numDrawnObjects)); if (g_SWVideoConfig.bHwRasterizer || drawingHwTriangles) { @@ -247,11 +238,13 @@ void OnObjectEnd() if (DrawnToBuffer[i]) { DrawnToBuffer[i] = false; - (void)SaveTGA(StringFromFormat("%sobject%i_%s(%i).tga", - File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), - swstats.thisFrame.numDrawnObjects, ObjectBufferName[i], i - BufferBase[i]).c_str(), - EFB_WIDTH, EFB_HEIGHT, ObjectBuffer[i]); + std::string filename = StringFromFormat("%sobject%i_%s(%i).png", + File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), + swstats.thisFrame.numDrawnObjects, ObjectBufferName[i], i - BufferBase[i]); + + (void)TextureToPng((u8*)ObjectBuffer[i], EFB_WIDTH * 4, filename, EFB_WIDTH, EFB_HEIGHT, true); memset(ObjectBuffer[i], 0, sizeof(ObjectBuffer[i])); + } } @@ -265,10 +258,10 @@ void OnFrameEnd() { if (g_SWVideoConfig.bDumpFrames) { - DumpEfb(StringFromFormat("%sframe%i_color.tga", - File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str()); - DumpDepth(StringFromFormat("%sframe%i_depth.tga", - File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount).c_str()); + DumpEfb(StringFromFormat("%sframe%i_color.png", + File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount)); + DumpDepth(StringFromFormat("%sframe%i_depth.png", + File::GetUserPath(D_DUMPFRAMES_IDX).c_str(), swstats.frameCount)); } } } diff --git a/Source/Core/VideoBackends/Software/Src/DebugUtil.h b/Source/Core/VideoBackends/Software/Src/DebugUtil.h index 3cbb318ffb..7d5ac4beea 100644 --- a/Source/Core/VideoBackends/Software/Src/DebugUtil.h +++ b/Source/Core/VideoBackends/Software/Src/DebugUtil.h @@ -9,7 +9,7 @@ namespace DebugUtil { void Init(); - void GetTextureBGRA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height); + void GetTextureRGBA(u8 *dst, u32 texmap, s32 mip, u32 width, u32 height); void DumpActiveTextures(); diff --git a/Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp b/Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp index 996b440dc4..88b3e15ebd 100644 --- a/Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp +++ b/Source/Core/VideoBackends/Software/Src/HwRasterizer.cpp @@ -329,15 +329,12 @@ namespace HwRasterizer int image_width = texImage0.width; int image_height = texImage0.height; - DebugUtil::GetTextureBGRA(temp, 0, 0, image_width, image_height); + DebugUtil::GetTextureRGBA(temp, 0, 0, image_width, image_height); glGenTextures(1, (GLuint *)&texture); glBindTexture(TEX2D, texture); -#ifdef USE_GLES glTexImage2D(TEX2D, 0, GL_RGBA, (GLsizei)image_width, (GLsizei)image_height, 0, GL_RGBA, GL_UNSIGNED_BYTE, temp); -#else - glTexImage2D(TEX2D, 0, GL_RGBA8, (GLsizei)image_width, (GLsizei)image_height, 0, GL_BGRA, GL_UNSIGNED_BYTE, temp); -#endif + GL_REPORT_ERRORD(); } diff --git a/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp b/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp index 1d894b18da..069ca5eebc 100644 --- a/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp +++ b/Source/Core/VideoBackends/Software/Src/SWRenderer.cpp @@ -5,6 +5,7 @@ #include "Common.h" #include "../../OGL/Src/GLUtil.h" +#include "ImageWrite.h" #include "RasterFont.h" #include "SWRenderer.h" #include "SWStatistics.h" @@ -17,6 +18,11 @@ static GLint attr_pos = -1, attr_tex = -1; static GLint uni_tex = -1; static GLuint program; +static volatile bool s_bScreenshot; +static std::mutex s_criticalScreenshot; +static std::string s_sScreenshotName; + + // Rasterfont isn't compatible with GLES // degasus: I think it does, but I can't test it #ifndef USE_GLES @@ -25,6 +31,7 @@ RasterFont* s_pfont = NULL; void SWRenderer::Init() { + s_bScreenshot = false; } void SWRenderer::Shutdown() @@ -80,6 +87,13 @@ void SWRenderer::Prepare() GL_REPORT_ERRORD(); } +void SWRenderer::SetScreenshot(const char *_szFilename) +{ + std::lock_guard lk(s_criticalScreenshot); + s_sScreenshotName = _szFilename; + s_bScreenshot = true; +} + void SWRenderer::RenderText(const char* pstr, int left, int top, u32 color) { #ifndef USE_GLES @@ -124,6 +138,15 @@ void SWRenderer::DrawDebugText() void SWRenderer::DrawTexture(u8 *texture, int width, int height) { + // Save screenshot + if (s_bScreenshot) + { + std::lock_guard lk(s_criticalScreenshot); + TextureToPng(texture, width*4, s_sScreenshotName, width, height, false); + // Reset settings + s_sScreenshotName.clear(); + s_bScreenshot = false; + } GLsizei glWidth = (GLsizei)GLInterface->GetBackBufferWidth(); GLsizei glHeight = (GLsizei)GLInterface->GetBackBufferHeight(); diff --git a/Source/Core/VideoBackends/Software/Src/SWRenderer.h b/Source/Core/VideoBackends/Software/Src/SWRenderer.h index ba856936cb..80a93ea203 100644 --- a/Source/Core/VideoBackends/Software/Src/SWRenderer.h +++ b/Source/Core/VideoBackends/Software/Src/SWRenderer.h @@ -6,13 +6,15 @@ #define _RENDERER_H_ #include "CommonTypes.h" +#include "Thread.h" namespace SWRenderer -{ +{ void Init(); void Prepare(); void Shutdown(); - + + void SetScreenshot(const char *_szFilename); void RenderText(const char* pstr, int left, int top, u32 color); void DrawDebugText(); diff --git a/Source/Core/VideoBackends/Software/Src/SWVideoConfig.cpp b/Source/Core/VideoBackends/Software/Src/SWVideoConfig.cpp index 43b6a96ef7..eb7cb79d40 100644 --- a/Source/Core/VideoBackends/Software/Src/SWVideoConfig.cpp +++ b/Source/Core/VideoBackends/Software/Src/SWVideoConfig.cpp @@ -65,8 +65,8 @@ void SWVideoConfig::Save(const char* ini_file) iniFile.Set("Hardware", "RenderToMainframe", renderToMainframe); iniFile.Set("Rendering", "HwRasterizer", bHwRasterizer); - iniFile.Set("Rendering", "ZComploc", &bZComploc); - iniFile.Set("Rendering", "ZFreeze", &bZFreeze); + iniFile.Set("Rendering", "ZComploc", bZComploc); + iniFile.Set("Rendering", "ZFreeze", bZFreeze); iniFile.Set("Info", "ShowStats", bShowStats); diff --git a/Source/Core/VideoBackends/Software/Src/SWmain.cpp b/Source/Core/VideoBackends/Software/Src/SWmain.cpp index 939dd4553a..074b6bc38b 100644 --- a/Source/Core/VideoBackends/Software/Src/SWmain.cpp +++ b/Source/Core/VideoBackends/Software/Src/SWmain.cpp @@ -236,7 +236,8 @@ u32 VideoSoftware::Video_GetQueryResult(PerfQueryType type) bool VideoSoftware::Video_Screenshot(const char *_szFilename) { - return false; + SWRenderer::SetScreenshot(_szFilename); + return true; } // ------------------------------- diff --git a/Source/Core/VideoCommon/CMakeLists.txt b/Source/Core/VideoCommon/CMakeLists.txt index 594624592c..9566712191 100644 --- a/Source/Core/VideoCommon/CMakeLists.txt +++ b/Source/Core/VideoCommon/CMakeLists.txt @@ -39,8 +39,7 @@ set(SRCS Src/BPFunctions.cpp Src/XFMemory.cpp Src/XFStructs.cpp Src/memcpy_amd.cpp) - -set(LIBS core) +set(LIBS core png) if(NOT _M_GENERIC) set(SRCS ${SRCS} Src/x64TextureDecoder.cpp diff --git a/Source/Core/VideoCommon/Src/BPMemory.cpp b/Source/Core/VideoCommon/Src/BPMemory.cpp index 7bc976a943..7272ed0993 100644 --- a/Source/Core/VideoCommon/Src/BPMemory.cpp +++ b/Source/Core/VideoCommon/Src/BPMemory.cpp @@ -19,18 +19,15 @@ void LoadBPReg(u32 value0) int opcode = value0 >> 24; int oldval = ((u32*)&bpmem)[opcode]; int newval = (oldval & ~bpmem.bpMask) | (value0 & bpmem.bpMask); + int changes = (oldval ^ newval) & 0xFFFFFF; + BPCmd bp = {opcode, changes, newval}; + + //reset the mask register if (opcode != 0xFE) - { - //reset the mask register bpmem.bpMask = 0xFFFFFF; - int changes = (oldval ^ newval) & 0xFFFFFF; - BPCmd bp = {opcode, changes, newval}; - BPWritten(bp); - } - else - bpmem.bpMask = newval; + BPWritten(bp); } void GetBPRegInfo(const u8* data, char* name, size_t name_size, char* desc, size_t desc_size) diff --git a/Source/Core/VideoCommon/Src/DriverDetails.cpp b/Source/Core/VideoCommon/Src/DriverDetails.cpp index 21b2273a49..1a9a56f532 100644 --- a/Source/Core/VideoCommon/Src/DriverDetails.cpp +++ b/Source/Core/VideoCommon/Src/DriverDetails.cpp @@ -27,7 +27,7 @@ namespace DriverDetails // This is a list of all known bugs for each vendor // We use this to check if the device and driver has a issue BugInfo m_known_bugs[] = { - {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_NODYNUBOACCESS, 14.0, -1.0, true}, + {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_NODYNUBOACCESS, 14.0, 46.0, true}, {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENCENTROID, 14.0, -1.0, true}, {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_BROKENINFOLOG, -1.0, -1.0, true}, {VENDOR_QUALCOMM, DRIVER_QUALCOMM_3XX, BUG_ANNIHILATEDUBOS, 41.0, 46.0, true}, diff --git a/Source/Core/VideoCommon/Src/DriverDetails.h b/Source/Core/VideoCommon/Src/DriverDetails.h index b9ace5b4f5..2a5fb3ce22 100644 --- a/Source/Core/VideoCommon/Src/DriverDetails.h +++ b/Source/Core/VideoCommon/Src/DriverDetails.h @@ -53,7 +53,7 @@ namespace DriverDetails // Bug: No Dynamic UBO array object access // Affected Devices: Qualcomm/Adreno // Started Version: 14 - // Ended Version: -1 + // Ended Version: 53 // Accessing UBO array members dynamically causes the Adreno shader compiler to crash // Errors out with "Internal Error" BUG_NODYNUBOACCESS = 0, @@ -102,7 +102,7 @@ namespace DriverDetails // Bug: Entirely broken UBOs // Affected devices: Qualcomm/Adreno // Started Version: ? (Noticed on v45) - // Ended Version: -1 + // Ended Version: 53 // Uniform buffers are entirely broken on Qualcomm drivers with v45 // Trying to use the uniform buffers causes a malloc to fail inside the driver // To be safe, blanket drivers from v41 - v45 diff --git a/Source/Core/VideoCommon/Src/ImageWrite.cpp b/Source/Core/VideoCommon/Src/ImageWrite.cpp index f53bd1c18f..193f058541 100644 --- a/Source/Core/VideoCommon/Src/ImageWrite.cpp +++ b/Source/Core/VideoCommon/Src/ImageWrite.cpp @@ -5,55 +5,10 @@ #include #include +#include "png.h" #include "ImageWrite.h" #include "FileUtil.h" -#pragma pack(push, 1) - -struct TGA_HEADER -{ - u8 identsize; // size of ID field that follows 18 u8 header (0 usually) - u8 colourmaptype; // type of colour map 0=none, 1=has palette - u8 imagetype; // type of image 0=none,1=indexed,2=rgb,3=grey,+8=rle packed - - s16 colourmapstart; // first colour map entry in palette - s16 colourmaplength; // number of colours in palette - u8 colourmapbits; // number of bits per palette entry 15,16,24,32 - - s16 xstart; // image x origin - s16 ystart; // image y origin - s16 width; // image width in pixels - s16 height; // image height in pixels - u8 bits; // image bits per pixel 8,16,24,32 - u8 descriptor; // image descriptor bits (vh flip bits) - - // pixel data follows header -}; - -#pragma pack(pop) - -bool SaveTGA(const char* filename, int width, int height, void* pdata) -{ - TGA_HEADER hdr; - File::IOFile f(filename, "wb"); - if (!f) - return false; - - _assert_(sizeof(TGA_HEADER) == 18 && sizeof(hdr) == 18); - - memset(&hdr, 0, sizeof(hdr)); - hdr.imagetype = 2; - hdr.bits = 32; - hdr.width = width; - hdr.height = height; - hdr.descriptor |= 8|(1<<5); // 8bit alpha, flip vertical - - f.WriteArray(&hdr, 1); - f.WriteBytes(pdata, width * height * 4); - - return true; -} - bool SaveData(const char* filename, const char* data) { std::ofstream f; @@ -62,3 +17,92 @@ bool SaveData(const char* filename, const char* data) return true; } + + +/* +TextureToPng + +Inputs: +data : This is an array of RGBA with 8 bits per channel. 4 bytes for each pixel. +row_stride: Determines the amount of bytes per row of pixels. +*/ +bool TextureToPng(u8* data, int row_stride, const std::string filename, int width, int height, bool saveAlpha) +{ + bool success = false; + + if (!data) + return false; + + char title[] = "Dolphin Screenshot"; + char title_key[] = "Title"; + png_structp png_ptr = NULL; + png_infop info_ptr = NULL; + + // Open file for writing (binary mode) + File::IOFile fp(filename, "wb"); + if (!fp.IsOpen()) { + PanicAlert("Screenshot failed: Could not open file %s %d\n", filename.c_str(), errno); + goto finalise; + } + + // Initialize write structure + png_ptr = png_create_write_struct(PNG_LIBPNG_VER_STRING, NULL, NULL, NULL); + if (png_ptr == NULL) { + PanicAlert("Screenshot failed: Could not allocate write struct\n"); + goto finalise; + + } + + // Initialize info structure + info_ptr = png_create_info_struct(png_ptr); + if (info_ptr == NULL) { + PanicAlert("Screenshot failed: Could not allocate info struct\n"); + goto finalise; + } + + // Setup Exception handling + if (setjmp(png_jmpbuf(png_ptr))) { + PanicAlert("Screenshot failed: Error during png creation\n"); + goto finalise; + } + + png_init_io(png_ptr, fp.GetHandle()); + + // Write header (8 bit colour depth) + png_set_IHDR(png_ptr, info_ptr, width, height, + 8, PNG_COLOR_TYPE_RGB_ALPHA, PNG_INTERLACE_NONE, + PNG_COMPRESSION_TYPE_BASE, PNG_FILTER_TYPE_BASE); + + png_text title_text; + title_text.compression = PNG_TEXT_COMPRESSION_NONE; + title_text.key = title_key; + title_text.text = title; + png_set_text(png_ptr, info_ptr, &title_text, 1); + + png_write_info(png_ptr, info_ptr); + + // Write image data + for (auto y = 0; y < height; ++y) + { + u8* row_ptr = (u8*)data + y * row_stride; + u8* ptr = row_ptr; + for (auto x = 0; x < row_stride / 4; ++x) + { + if (!saveAlpha) + ptr[3] = 0xff; + ptr += 4; + } + png_write_row(png_ptr, row_ptr); + } + + // End write + png_write_end(png_ptr, NULL); + + success = true; + +finalise: + if (info_ptr != NULL) png_free_data(png_ptr, info_ptr, PNG_FREE_ALL, -1); + if (png_ptr != NULL) png_destroy_write_struct(&png_ptr, (png_infopp)NULL); + + return success; +} diff --git a/Source/Core/VideoCommon/Src/ImageWrite.h b/Source/Core/VideoCommon/Src/ImageWrite.h index 7d1d6fa1e8..04de765d32 100644 --- a/Source/Core/VideoCommon/Src/ImageWrite.h +++ b/Source/Core/VideoCommon/Src/ImageWrite.h @@ -7,8 +7,8 @@ #include "Common.h" -bool SaveTGA(const char* filename, int width, int height, void* pdata); bool SaveData(const char* filename, const char* pdata); +bool TextureToPng(u8* data, int row_stride, const std::string filename, int width, int height, bool saveAlpha = true); #endif // _IMAGEWRITE_H diff --git a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp index 442cfc1ef4..f107da783e 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/PixelShaderGen.cpp @@ -316,8 +316,10 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T // compute window position if needed because binding semantic WPOS is not widely supported // Let's set up attributes - for (int i = 0; i < xfregs.numTexGen.numTexGens; ++i) + for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i) + { out.Write("VARYIN float3 uv%d_2;\n", i); + } out.Write("VARYIN float4 clipPos_2;\n"); if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting) { @@ -392,9 +394,13 @@ static inline void GeneratePixelShader(T& out, DSTALPHA_MODE dstAlphaMode, API_T out.Write("float4 colors_1 = colors_12;\n"); // compute window position if needed because binding semantic WPOS is not widely supported // Let's set up attributes - if(numTexgen) - for (int i = 0; i < xfregs.numTexGen.numTexGens; ++i) + if (numTexgen) + { + for (unsigned int i = 0; i < xfregs.numTexGen.numTexGens; ++i) + { out.Write("float3 uv%d = uv%d_2;\n", i, i); + } + } out.Write("float4 clipPos = clipPos_2;\n"); if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting) { diff --git a/Source/Core/VideoCommon/Src/PixelShaderManager.cpp b/Source/Core/VideoCommon/Src/PixelShaderManager.cpp index b999ada6a3..98722e48ce 100644 --- a/Source/Core/VideoCommon/Src/PixelShaderManager.cpp +++ b/Source/Core/VideoCommon/Src/PixelShaderManager.cpp @@ -84,7 +84,7 @@ void PixelShaderManager::SetConstants(u32 components) // they are the coefficients from the center to the border of the screen // so to simplify I use the hi coefficient as K in the shader taking 256 as the scale constants.fog[2][0] = ScreenSpaceCenter; - constants.fog[2][1] = Renderer::EFBToScaledX((int)(2.0f * xfregs.viewport.wd)); + constants.fog[2][1] = (float)Renderer::EFBToScaledX((int)(2.0f * xfregs.viewport.wd)); constants.fog[2][2] = bpmem.fogRange.K[4].HI / 256.0f; } else @@ -263,8 +263,8 @@ void PixelShaderManager::SetZTextureTypeChanged() void PixelShaderManager::SetTexCoordChanged(u8 texmapid) { TCoordInfo& tc = bpmem.texcoords[texmapid]; - constants.texdims[texmapid][2] = tc.s.scale_minus_1 + 1; - constants.texdims[texmapid][3] = tc.t.scale_minus_1 + 1; + constants.texdims[texmapid][2] = (float)(tc.s.scale_minus_1 + 1); + constants.texdims[texmapid][3] = (float)(tc.t.scale_minus_1 + 1); dirty = true; } @@ -283,7 +283,7 @@ void PixelShaderManager::SetFogParamChanged() constants.fog[1][0] = bpmem.fog.a.GetA(); constants.fog[1][1] = (float)bpmem.fog.b_magnitude / 0xFFFFFF; constants.fog[1][2] = bpmem.fog.c_proj_fsel.GetC(); - constants.fog[1][3] = 1 << bpmem.fog.b_shift; + constants.fog[1][3] = (float)(1 << bpmem.fog.b_shift); } else { diff --git a/Source/Core/VideoCommon/Src/RenderBase.cpp b/Source/Core/VideoCommon/Src/RenderBase.cpp index bb3dad8a73..e509ccb980 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.cpp +++ b/Source/Core/VideoCommon/Src/RenderBase.cpp @@ -30,12 +30,6 @@ #include "XFMemory.h" #include "FifoPlayer/FifoRecorder.h" #include "AVIDump.h" -#include "OnScreenDisplay.h" -#if defined(HAVE_WX) && HAVE_WX -#include "WxUtils.h" -#include -#endif -#include "ImageWrite.h" #include #include @@ -73,8 +67,6 @@ unsigned int Renderer::efb_scale_numeratorY = 1; unsigned int Renderer::efb_scale_denominatorX = 1; unsigned int Renderer::efb_scale_denominatorY = 1; -// TODO: remove -extern bool g_aspect_wide; Renderer::Renderer() : frame_data() @@ -250,72 +242,6 @@ void Renderer::SetScreenshot(const char *filename) s_bScreenshot = true; } -#if defined(HAVE_WX) && HAVE_WX -void Renderer::SaveScreenshotOnThread(u8* data, size_t width, size_t height, std::string filename) -{ - wxImage *img = new wxImage(width, height, data); - - // These will contain the final image size - float FloatW = (float)width; - float FloatH = (float)height; - - // Handle aspect ratio for the final ScrStrct to look exactly like what's on screen. - if (g_ActiveConfig.iAspectRatio != ASPECT_STRETCH) - { - bool use16_9 = g_aspect_wide; - - // Check for force-settings and override. - if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_16_9) - use16_9 = true; - else if (g_ActiveConfig.iAspectRatio == ASPECT_FORCE_4_3) - use16_9 = false; - - float Ratio = (FloatW / FloatH) / (!use16_9 ? (4.0f / 3.0f) : (16.0f / 9.0f)); - - // If ratio > 1 the picture is too wide and we have to limit the width. - if (Ratio > 1) - FloatW /= Ratio; - // ratio == 1 or the image is too high, we have to limit the height. - else - FloatH *= Ratio; - - // This is a bit expensive on high resolutions - img->Rescale((int)FloatW, (int)FloatH, wxIMAGE_QUALITY_HIGH); - } - - // Save the screenshot and finally kill the wxImage object - // This is really expensive when saving to PNG, but not at all when using BMP - img->SaveFile(StrToWxStr(filename), wxBITMAP_TYPE_PNG); - img->Destroy(); - - // Show success messages - OSD::AddMessage(StringFromFormat("Saved %i x %i %s", (int)FloatW, (int)FloatH, - filename.c_str()), 2000); -} -#endif - -void Renderer::SaveScreenshot(u8* ptr, size_t width, size_t height, std::string filename) -{ - std::lock_guard lk(s_criticalScreenshot); -#if defined(HAVE_WX) && HAVE_WX - // Create wxImage - - std::thread thread(SaveScreenshotOnThread, ptr, width, height, filename); -#ifdef _WIN32 - SetThreadPriority(thread.native_handle(), THREAD_PRIORITY_BELOW_NORMAL); -#endif - thread.detach(); - - OSD::AddMessage("Saving Screenshot... ", 2000); - -#else - SaveTGA(filename.c_str(), width, height, ptr); - free(ptr); -#endif - - s_bScreenshot = false; -} - // Create On-Screen-Messages void Renderer::DrawDebugText() { @@ -421,6 +347,9 @@ void Renderer::DrawDebugText() g_renderer->RenderText(final_yellow.c_str(), 20, 20, 0xFFFFFF00); } +// TODO: remove +extern bool g_aspect_wide; + void Renderer::UpdateDrawRectangle(int backbuffer_width, int backbuffer_height) { float FloatGLWidth = (float)backbuffer_width; diff --git a/Source/Core/VideoCommon/Src/RenderBase.h b/Source/Core/VideoCommon/Src/RenderBase.h index 7a153fb5cc..22d31cde23 100644 --- a/Source/Core/VideoCommon/Src/RenderBase.h +++ b/Source/Core/VideoCommon/Src/RenderBase.h @@ -110,6 +110,8 @@ public: virtual void UpdateViewport() = 0; + virtual bool SaveScreenshot(const std::string &filename, const TargetRectangle &rc) = 0; + static unsigned int GetPrevPixelFormat() { return prev_efb_format; } static void StorePixelFormat(unsigned int new_format) { prev_efb_format = new_format; } @@ -121,11 +123,6 @@ protected: static void CheckFifoRecording(); static void RecordVideoMemory(); - #if defined(HAVE_WX) && HAVE_WX - static void SaveScreenshotOnThread(u8* data, size_t width, size_t height, std::string filename); - #endif - static void SaveScreenshot(u8* ptr, size_t width, size_t height, std::string filename); - static volatile bool s_bScreenshot; static std::mutex s_criticalScreenshot; static std::string s_sScreenshotName; diff --git a/Source/Core/VideoCommon/Src/ShaderGenCommon.h b/Source/Core/VideoCommon/Src/ShaderGenCommon.h index 35ec50407a..b56e9f29ff 100644 --- a/Source/Core/VideoCommon/Src/ShaderGenCommon.h +++ b/Source/Core/VideoCommon/Src/ShaderGenCommon.h @@ -236,7 +236,7 @@ public: u32 value = ((u32*)&new_uid.GetUidData())[i]; if ((i % 4) == 0) { - unsigned int last_value = (i+3 < new_uid.GetUidDataSize()-1) ? i+3 : new_uid.GetUidDataSize(); + auto last_value = (i+3 < new_uid.GetUidDataSize()-1) ? i+3 : new_uid.GetUidDataSize(); file << std::setfill(' ') << std::dec; file << "Values " << std::setw(2) << i << " - " << last_value << ": "; } diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp index 41af7ac946..31ba3d5e61 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.cpp +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.cpp @@ -30,8 +30,6 @@ unsigned int TextureCache::temp_size; TextureCache::TexCache TextureCache::textures; -TextureCache::TexPool TextureCache::texPool; - TextureCache::BackupConfig TextureCache::backup_config; bool invalidate_texture_cache_requested; @@ -70,13 +68,6 @@ void TextureCache::Invalidate() delete iter->second; textures.clear(); - - TexPool::iterator - iter2 = texPool.begin(), - tcend2 = texPool.end(); - for (; iter2 != tcend2; ++iter2) - delete iter2->second; - texPool.clear(); } TextureCache::~TextureCache() @@ -144,7 +135,7 @@ void TextureCache::Cleanup() // EFB copies living on the host GPU are unrecoverable and thus shouldn't be deleted && ! iter->second->IsEfbCopy() ) { - PoolTexture(iter->second); + delete iter->second; textures.erase(iter++); } else @@ -152,21 +143,6 @@ void TextureCache::Cleanup() ++iter; } } - - TexPool::iterator iter2 = texPool.begin(); - TexPool::iterator tcend2 = texPool.end(); - while (iter2 != tcend2) - { - if (frameCount > TEXTURE_KILL_THRESHOLD + iter2->second->frameCount) - { - delete iter2->second; - texPool.erase(iter2++); - } - else - { - ++iter2; - } - } } void TextureCache::InvalidateRange(u32 start_address, u32 size) @@ -179,7 +155,7 @@ void TextureCache::InvalidateRange(u32 start_address, u32 size) const int rangePosition = iter->second->IntersectsMemoryRange(start_address, size); if (0 == rangePosition) { - PoolTexture(iter->second); + delete iter->second; textures.erase(iter++); } else @@ -239,7 +215,7 @@ void TextureCache::ClearRenderTargets() { if (iter->second->type == TCET_EC_VRAM) { - PoolTexture(iter->second); + delete iter->second; textures.erase(iter++); } else @@ -307,7 +283,7 @@ PC_TexFormat TextureCache::LoadCustomTexture(u64 tex_hash, int texformat, unsign void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level) { - char szTemp[MAX_PATH]; + std::string filename; std::string szDir = File::GetUserPath(D_DUMPTEXTURES_IDX) + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID; @@ -319,19 +295,19 @@ void TextureCache::DumpTexture(TCacheEntryBase* entry, unsigned int level) // TODO: TLUT format should actually be stored in filename? :/ if (level == 0) { - sprintf(szTemp, "%s/%s_%08x_%i.png", szDir.c_str(), - SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), - (u32) (entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF); + filename = StringFromFormat("%s/%s_%08x_%i.png", szDir.c_str(), + SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), + (u32)(entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF); } else { - sprintf(szTemp, "%s/%s_%08x_%i_mip%i.png", szDir.c_str(), + filename = StringFromFormat("%s/%s_%08x_%i_mip%i.png", szDir.c_str(), SConfig::GetInstance().m_LocalCoreStartupParameter.m_strUniqueID.c_str(), (u32) (entry->hash & 0x00000000FFFFFFFFLL), entry->format & 0xFFFF, level); } - if (false == File::Exists(szTemp)) - entry->Save(szTemp, level); + if (!File::Exists(filename)) + entry->Save(filename, level); } static u32 CalculateLevelSize(u32 level_0_size, u32 level) @@ -450,8 +426,8 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, } else { - // pool the texture and make a new one - PoolTexture(entry); + // delete the texture and make a new one + delete entry; entry = NULL; } } @@ -470,8 +446,11 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, expandedHeight = height; // If we thought we could reuse the texture before, make sure to pool it now! - PoolTexture(entry); - entry = NULL; + if(entry) + { + delete entry; + entry = NULL; + } } using_custom_texture = true; } @@ -497,15 +476,6 @@ TextureCache::TCacheEntryBase* TextureCache::Load(unsigned int const stage, const bool use_native_mips = use_mipmaps && !using_custom_lods && (width == nativeW && height == nativeH); texLevels = (use_native_mips || using_custom_lods) ? texLevels : 1; // TODO: Should be forced to 1 for non-pow2 textures (e.g. efb copies with automatically adjusted IR) - // try to search for a pooled texture - if (NULL == entry) - { - // Try to find a matching texture in the pool. We pool unused texture as they often just change the type. - // This happens in eg efb2ram which overwrites half of a texture. So most of this textures are only pooled - // for some frames. - textures[texID] = entry = GetPooledTexture ( width, height, full_format, texLevels, false ); - } - // create the entry/texture if (NULL == entry) { @@ -854,23 +824,16 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat else if (!(entry->type == TCET_EC_VRAM && entry->virtual_width == scaled_tex_w && entry->virtual_height == scaled_tex_h)) { // remove it and recreate it as a render target - PoolTexture(entry); + delete entry; entry = NULL; } } if (NULL == entry) { - // search for a compatible pooled texture - entry = GetPooledTexture(scaled_tex_w, scaled_tex_h, 0, 0, true); - - if (NULL == entry) - { - // create the texture - entry = g_texture_cache->CreateRenderTargetTexture(scaled_tex_w, scaled_tex_h); - } - textures[dstAddr] = entry; - + // create the texture + textures[dstAddr] = entry = g_texture_cache->CreateRenderTargetTexture(scaled_tex_w, scaled_tex_h); + // TODO: Using the wrong dstFormat, dumb... entry->SetGeneralParameters(dstAddr, 0, dstFormat, 1); entry->SetDimensions(tex_w, tex_h, scaled_tex_w, scaled_tex_h); @@ -882,33 +845,3 @@ void TextureCache::CopyRenderTargetToTexture(u32 dstAddr, unsigned int dstFormat entry->FromRenderTarget(dstAddr, dstFormat, srcFormat, srcRect, isIntensity, scaleByHalf, cbufid, colmat); } - -TextureCache::TCacheEntryBase* TextureCache::GetPooledTexture ( u32 width, u32 height, u32 full_format, u32 maxlevel, bool isEfbCopy ) -{ - TCacheEntryBase* entry = NULL; - std::pair bounds; - bounds = texPool.equal_range(std::make_pair(width, height)); - while(!entry && bounds.first != bounds.second) { - entry = bounds.first->second; - if ( - (isEfbCopy && entry->IsEfbCopy()) || - (!isEfbCopy && entry->type == TCET_NORMAL && full_format == entry->format && entry->num_mipmaps == maxlevel) || - (!isEfbCopy && entry->type == TCET_EC_DYNAMIC) - ) - { - texPool.erase(bounds.first); - } - else - { - entry = NULL; - bounds.first++; - } - } - return entry; -} - -void TextureCache::PoolTexture(TextureCache::TCacheEntryBase* entry) -{ - entry->frameCount = frameCount; - texPool.insert(std::make_pair(std::make_pair(entry->virtual_width, entry->virtual_height), entry)); -} diff --git a/Source/Core/VideoCommon/Src/TextureCacheBase.h b/Source/Core/VideoCommon/Src/TextureCacheBase.h index c035ee8d23..4db768f5e4 100644 --- a/Source/Core/VideoCommon/Src/TextureCacheBase.h +++ b/Source/Core/VideoCommon/Src/TextureCacheBase.h @@ -73,7 +73,7 @@ public: virtual ~TCacheEntryBase(); virtual void Bind(unsigned int stage) = 0; - virtual bool Save(const char filename[], unsigned int level) = 0; + virtual bool Save(const std::string filename, unsigned int level) = 0; virtual void Load(unsigned int width, unsigned int height, unsigned int expanded_width, unsigned int level) = 0; @@ -121,12 +121,8 @@ private: static void DumpTexture(TCacheEntryBase* entry, unsigned int level); typedef std::map TexCache; + static TexCache textures; - - static TCacheEntryBase* GetPooledTexture(u32 width, u32 height, u32 full_format, u32 maxlevel, bool isEfbCopy); - static void PoolTexture(TCacheEntryBase *entry); - typedef std::multimap, TCacheEntryBase*> TexPool; - static TexPool texPool; // Backup configuration values static struct BackupConfig diff --git a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp index f36f857973..78b3c57dda 100644 --- a/Source/Core/VideoCommon/Src/VertexShaderGen.cpp +++ b/Source/Core/VideoCommon/Src/VertexShaderGen.cpp @@ -130,9 +130,13 @@ static inline void GenerateVertexShader(T& out, u32 components, API_TYPE api_typ } // Let's set up attributes - for (int i = 0; i < 8; ++i) + for (size_t i = 0; i < 8; ++i) + { if (i < xfregs.numTexGen.numTexGens) + { out.Write("VARYOUT float3 uv%d_2;\n", i); + } + } out.Write("VARYOUT float4 clipPos_2;\n"); if (g_ActiveConfig.bEnablePixelLighting && g_ActiveConfig.backend_info.bSupportsPixelLighting) out.Write("VARYOUT float4 Normal_2;\n"); diff --git a/Source/Core/VideoCommon/Src/x64TextureDecoder.cpp b/Source/Core/VideoCommon/Src/x64TextureDecoder.cpp index 6887a0bdd0..a02738479a 100644 --- a/Source/Core/VideoCommon/Src/x64TextureDecoder.cpp +++ b/Source/Core/VideoCommon/Src/x64TextureDecoder.cpp @@ -1460,7 +1460,7 @@ PC_TexFormat TexDecoder_Decode_RGBA(u32 * dst, const u8 * src, int width, int he for (int iy = 0, xStep = 4 * yStep; iy < 4; iy++, xStep++) { u32 *newdst = dst+(y+iy)*width+x; - const __m128i mask = _mm_set_epi8(128,128,6,7,128,128,4,5,128,128,2,3,128,128,0,1); + const __m128i mask = _mm_set_epi8(-128,-128,6,7,-128,-128,4,5,-128,-128,2,3,-128,-128,0,1); const __m128i valV = _mm_shuffle_epi8(_mm_loadl_epi64((const __m128i*)(src + 8 * xStep)),mask); int cmp = _mm_movemask_epi8(valV); //MSB: 0x2 = val0; 0x20=val1; 0x200 = val2; 0x2000=val3 if ((cmp&0x2222)==0x2222) // SSSE3 case #1: all 4 pixels are in RGB555 and alpha = 0xFF. diff --git a/Source/Core/VideoCommon/VideoCommon.vcxproj b/Source/Core/VideoCommon/VideoCommon.vcxproj index dd8bbc6f6d..fa7ef921ae 100644 --- a/Source/Core/VideoCommon/VideoCommon.vcxproj +++ b/Source/Core/VideoCommon/VideoCommon.vcxproj @@ -152,9 +152,15 @@ {aa862e5e-a993-497a-b6a0-0e8e94b10050} + + {4c9f135b-a85e-430c-bad4-4c67ef5fc12c} + {b441cc62-877e-4b3f-93e0-0de80544f705} + + {ff213b23-2c26-4214-9f88-85271e557e87} + {2e6c348c-c75c-4d94-8d1e-9c1fcbf3efe4} diff --git a/Source/VSProps/Base.props b/Source/VSProps/Base.props index 2ee5bd8e8e..1b40800891 100644 --- a/Source/VSProps/Base.props +++ b/Source/VSProps/Base.props @@ -44,6 +44,7 @@ $(ExternalsDir)Bochs_disasm;%(AdditionalIncludeDirectories) $(ExternalsDir)CLRun\include;%(AdditionalIncludeDirectories) $(ExternalsDir)GLew\include;%(AdditionalIncludeDirectories) + $(ExternalsDir)libpng;%(AdditionalIncludeDirectories) $(ExternalsDir)libusbx\libusb;%(AdditionalIncludeDirectories) $(ExternalsDir)LZO;%(AdditionalIncludeDirectories) $(ExternalsDir)miniupnpc\src;%(AdditionalIncludeDirectories)