Merge branch 'master' into android-new-control-input-overlay

Conflicts:
	Source/Android/res/values-ja/strings.xml
	Source/Android/res/values/strings.xml
	Source/Android/src/org/dolphinemu/dolphinemu/AboutFragment.java
	Source/Android/src/org/dolphinemu/dolphinemu/emulation/EmulationActivity.java
	Source/Android/src/org/dolphinemu/dolphinemu/folderbrowser/FolderBrowser.java
	Source/Android/src/org/dolphinemu/dolphinemu/gamelist/GameListActivity.java
	Source/Android/src/org/dolphinemu/dolphinemu/settings/video/VideoSettingsFragment.java
This commit is contained in:
Ryan Houdek
2013-11-24 16:12:00 -06:00
154 changed files with 1743 additions and 1079 deletions
@@ -8,8 +8,12 @@
<!-- Save State Slots -->
<item
android:id="@+id/saveStateRoot"
android:id="@+id/takeScreenshot"
android:showAsAction="ifRoom"
android:title="@string/overlay_screenshot"/>
<item
android:id="@+id/saveStateRoot"
android:showAsAction="never"
android:title="@string/overlay_savestate">
<menu>
<item android:id="@+id/saveSlot1"
@@ -32,7 +36,7 @@
<!-- Load State Slots -->
<item
android:id="@+id/loadStateRoot"
android:showAsAction="ifRoom"
android:showAsAction="never"
android:title="@string/overlay_loadstate">
<menu>
<item android:id="@+id/loadSlot1"
+6
View File
@@ -11,6 +11,7 @@
<!-- About Fragment -->
<string name="build_revision">ビルドのバージョン</string>
<string name="supports_gles3">サポートのOpenGL ES 3</string>
<string name="supports_neon">サポートのNEON</string>
<!-- Folder Browser -->
<string name="current_dir">現在のディレクトリ: %1$s</string>
@@ -25,12 +26,17 @@
<string name="settings">設定</string>
<string name="about">について</string>
<!-- Game List Activity - Device Compatibility AlertDialog -->
<string name="device_compat_warning">デバイスの互換性の警告</string>
<string name="device_compat_warning_msg">この電話は、NEON拡張をサポートしていません。 おそらくDolphinを実行することはできません。\nあなたはとにかくそれを実行してみますか?</string>
<!-- Game List Fragment -->
<string name="file_clicked">クリックされたファイル: %1$s</string>
<!-- Emulation Window Overlay -->
<string name="enable_input_overlay">入力オーバーレイを有効</string>
<string name="disable_input_overlay">入力オーバーレイを無効</string>
<string name="overlay_screenshot">スクリーンショットを撮る</string>
<string name="overlay_savestate">ステートセーブ</string>
<string name="overlay_loadstate">ステートロード</string>
<string name="overlay_exit_emulation">終了</string>
+6
View File
@@ -11,6 +11,7 @@
<!-- About Fragment -->
<string name="build_revision">Build Revision</string>
<string name="supports_gles3">Supports OpenGL ES 3</string>
<string name="supports_neon">Supports NEON</string>
<!-- Folder Browser -->
<string name="current_dir">Current Dir: %1$s</string>
@@ -25,12 +26,17 @@
<string name="settings">Settings</string>
<string name="about">About</string>
<!-- Game List Activity - Device Compatibility AlertDialog -->
<string name="device_compat_warning">Device Compatibility Warning</string>
<string name="device_compat_warning_msg">Your phone doesn\'t support NEON which makes it incapable of running Dolphin Mobile?\nDo you want to try anyway?</string>
<!-- Game List Fragment -->
<string name="file_clicked">File clicked: %1$s</string>
<!-- Emulation Overlay -->
<string name="enable_input_overlay">Enable Input Overlay</string>
<string name="disable_input_overlay">Disable Input Overlay</string>
<string name="overlay_screenshot">Take Screenshot</string>
<string name="overlay_savestate">Save State</string>
<string name="overlay_loadstate">Load State</string>
<string name="overlay_exit_emulation">Exit</string>
@@ -29,21 +29,21 @@ public final class AboutFragment 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);
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<AboutFragmentItem> Input = new ArrayList<AboutFragmentItem>();
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(getActivity(), R.layout.about_layout, Input);
mMainList.setAdapter(adapter);
mMainList.setEnabled(false); // Makes the list view non-clickable.
rootView.setAdapter(adapter);
rootView.setEnabled(false); // Makes the list view non-clickable.
return mMainList;
return rootView;
}
// Represents an item in the AboutFragment.
@@ -94,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());
@@ -114,7 +113,7 @@ public final class AboutFragment extends ListFragment
subtitle.setText(item.getSubTitle());
}
return v;
return convertView;
}
}
}
@@ -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.
}
}
@@ -152,6 +152,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.
*
@@ -64,12 +64,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.
sharedPrefs = PreferenceManager.getDefaultSharedPreferences(this);
if (sharedPrefs.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);
@@ -204,6 +206,11 @@ public final class EmulationActivity extends Activity
return true;
}
// Screenshot capturing
case R.id.takeScreenshot:
NativeLibrary.SaveScreenShot();
return true;
// Save state slots
case R.id.saveSlot1:
NativeLibrary.SaveState(0);
@@ -37,16 +37,17 @@ import org.dolphinemu.dolphinemu.gamelist.GameListActivity;
public final class FolderBrowser extends ListFragment
{
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)
{
// Change the activity title to reflect the current directory the FolderBrowser is in.
// 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<FolderBrowserItem> dir = new ArrayList<FolderBrowserItem>();
List<FolderBrowserItem> fls = new ArrayList<FolderBrowserItem>();
@@ -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(getActivity(), 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,10 +123,12 @@ 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;
}
private void FolderSelected()
@@ -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<FolderBrowserItem>
{
// 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<FolderBrowserItem> 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<FolderBrowserItem> 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;
}
}
@@ -9,10 +9,11 @@ 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;
@@ -41,7 +42,6 @@ public final class GameListActivity extends Activity
implements GameListFragment.OnGameListZeroListener
{
private int mCurFragmentNum = 0;
private Fragment mCurFragment;
private ActionBarDrawerToggle mDrawerToggle;
private DrawerLayout mDrawerLayout;
@@ -102,10 +102,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();
}
}
/**
@@ -129,9 +155,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;
@@ -139,9 +166,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;
@@ -156,9 +185,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;
@@ -245,7 +276,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() {
@@ -260,7 +291,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()
{
@@ -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<GameListItem>
{
private final Context context;
private final int id;
private final List<GameListItem>items;
/**
* 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<GameListItem> 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<GameListItem>
}
}
return v;
return convertView;
}
}
@@ -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)
{
@@ -27,6 +27,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;
/**
* Class which provides a means to retrieve various
@@ -163,7 +164,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)
{
@@ -174,20 +174,12 @@ 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;
}
}
if (!mSupportsGLES3 &&
m_GLVendor != null && m_GLVendor.equals("NVIDIA Corporation") &&
m_GLRenderer != null && m_GLRenderer.equals("NVIDIA Tegra") &&
m_GLExtensions != null && m_GLExtensions.contains("GL_OES_depth24"))
{
// Is a Tegra 4 since it supports 24bit depth
mSupportsGLES3 = true;
}
return mSupportsGLES3;
}
@@ -54,23 +54,22 @@ public final class SideMenuAdapter extends ArrayAdapter<SideMenuItem>
@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;
}
}
+6
View File
@@ -43,6 +43,12 @@ struct CPUInfo
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;
+1 -1
View File
@@ -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:
@@ -26,7 +26,7 @@ namespace FPURoundMode
void SetPrecisionMode(u32 mode)
{
}
void SetSIMDMode(u32 mode)
void SetSIMDMode(u32 mode, u32 nonIEEEMode)
{
}
void SaveSIMDState()
+2 -2
View File
@@ -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;
}
+34 -1
View File
@@ -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?
@@ -222,7 +250,12 @@ 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";
+24 -8
View File
@@ -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 <xmmintrin.h>
#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);
}
+6 -3
View File
@@ -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
+9 -5
View File
@@ -113,13 +113,17 @@ static bool VerifyRoms(const char *irom_filename, const char *coef_filename)
}
if (rom_idx == 1)
PanicAlertT("You are using an old free DSP ROM made by the Dolphin Team.\n"
"Only games using the Zelda UCode will work correctly.\n");
{
DSPHost_OSD_AddMessage("You are using an old free DSP ROM made by the Dolphin Team.", 6000);
DSPHost_OSD_AddMessage("Only games using the Zelda UCode will work correctly.", 6000);
}
if (rom_idx == 2)
PanicAlertT("You are using a free DSP ROM made by the Dolphin Team.\n"
"All Wii games will work correctly, and most GC games should "
"also work fine, but the GBA/IPL/CARD UCodes will not work.\n");
{
DSPHost_OSD_AddMessage("You are using a free DSP ROM made by the Dolphin Team.", 8000);
DSPHost_OSD_AddMessage("All Wii games will work correctly, and most GC games should ", 8000);
DSPHost_OSD_AddMessage("also work fine, but the GBA/IPL/CARD UCodes will not work.\n", 8000);
}
return true;
}
+1
View File
@@ -12,6 +12,7 @@
u8 DSPHost_ReadHostMemory(u32 addr);
void DSPHost_WriteHostMemory(u8 value, u32 addr);
void DSPHost_OSD_AddMessage(const std::string& str, u32 ms);
bool DSPHost_OnThread();
bool DSPHost_Wii();
void DSPHost_InterruptRequest();
@@ -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));
@@ -234,7 +234,7 @@ u32 FifoPlaybackAnalyzer::DecodeCommand(u8 *data)
break;
}
return data - dataStart;
return (u32)(data - dataStart);
}
void FifoPlaybackAnalyzer::StoreEfbCopyRegion()
@@ -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)
{
@@ -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];
@@ -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
}
@@ -13,6 +13,7 @@
#include "../../ConfigManager.h"
#include "../../PowerPC/PowerPC.h"
#include "Host.h"
#include "OnScreenDisplay.h"
// The user of the DSPCore library must supply a few functions so that the
// emulation core can access the environment it runs in. If the emulation
@@ -29,6 +30,11 @@ void DSPHost_WriteHostMemory(u8 value, u32 addr)
DSP::WriteARAM(value, addr);
}
void DSPHost_OSD_AddMessage(const std::string& str, u32 ms)
{
OSD::AddMessage(str, ms);
}
bool DSPHost_OnThread()
{
const SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;
+1 -1
View File
@@ -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.");
@@ -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)
+5 -5
View File
@@ -40,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:
@@ -63,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;
}
}
+1 -1
View File
@@ -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());
}
@@ -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<ReadRequest> tmp_queue(m_read_requests);
size = m_read_requests.size();
size = (u32)(m_read_requests.size());
p.Do(size);
while (!tmp_queue.empty())
{
@@ -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());
}
}
}
@@ -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_);
}
@@ -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;
}
@@ -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
@@ -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<Wiimote*> & 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<u8*>(buf) + 1, len - 1);
auto result = HidD_SetOutputReport(dev_handle, const_cast<u8*>(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);
}
@@ -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*>((void *)buf) length: len refcon: nil];
ret = [ichan writeAsync: const_cast<void*>((void *)buf) length: (int)len refcon: nil];
if (ret == kIOReturnSuccess)
return len;
@@ -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)
@@ -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();
+4 -2
View File
@@ -83,7 +83,7 @@ static u64 last_reply_time;
void EnqueReplyCallback(u64 userdata, int)
{
std::lock_guard<std::mutex> 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;
@@ -133,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;
@@ -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");
@@ -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
@@ -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");
+5 -4
View File
@@ -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<std::recursive_mutex> lks(m_crit.send);
m_socket.Send(spac);
+4 -2
View File
@@ -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;
@@ -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<float>(_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;
}
@@ -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)
+9 -6
View File
@@ -276,7 +276,7 @@ void Jit64::Cleanup()
ABI_CallFunctionCCC((void *)&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, jit->js.numLoadStoreInst, jit->js.numFloatingPointInst);
}
void Jit64::WriteExit(u32 destination, int exit_num)
void Jit64::WriteExit(u32 destination)
{
Cleanup();
@@ -284,8 +284,9 @@ void Jit64::WriteExit(u32 destination, int exit_num)
//If nobody has taken care of this yet (this can be removed when all branches are done)
JitBlock *b = js.curBlock;
b->exitAddress[exit_num] = destination;
b->exitPtrs[exit_num] = GetWritableCodePtr();
JitBlock::LinkData linkData;
linkData.exitAddress = destination;
linkData.exitPtrs = GetWritableCodePtr();
// Link opportunity!
if (jo.enableBlocklink)
@@ -295,12 +296,14 @@ void Jit64::WriteExit(u32 destination, int exit_num)
{
// It exists! Joy of joy!
JMP(blocks.GetBlock(block)->checkedEntry, true);
b->linkStatus[exit_num] = true;
linkData.linkStatus = true;
return;
}
}
MOV(32, M(&PC), Imm32(destination));
JMP(asm_routines.dispatcher, true);
b->linkData.push_back(linkData);
}
void Jit64::WriteExitDestInEAX()
@@ -625,7 +628,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = J_CC(CC_Z);
WriteExit(ops[i].address, 0);
WriteExit(ops[i].address);
SetJumpTarget(noBreakpoint);
}
@@ -707,7 +710,7 @@ const u8* Jit64::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
{
gpr.Flush(FLUSH_ALL);
fpr.Flush(FLUSH_ALL);
WriteExit(nextPC, 0);
WriteExit(nextPC);
}
b->flags = js.block_flags;
+2 -2
View File
@@ -99,7 +99,7 @@ public:
// Utilities for use by opcodes
void WriteExit(u32 destination, int exit_num);
void WriteExit(u32 destination);
void WriteExitDestInEAX();
void WriteExceptionExit();
void WriteExternalExceptionExit();
@@ -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);
@@ -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}},
@@ -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;
@@ -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();
@@ -91,7 +91,7 @@ void Jit64::bx(UGeckoInstruction inst)
// make idle loops go faster
js.downcountAmount += 8;
}
WriteExit(destination, 0);
WriteExit(destination);
}
// TODO - optimize to hell and beyond
@@ -136,13 +136,13 @@ void Jit64::bcx(UGeckoInstruction inst)
destination = SignExt16(inst.BD << 2);
else
destination = js.compilerPC + SignExt16(inst.BD << 2);
WriteExit(destination, 0);
WriteExit(destination);
if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0)
SetJumpTarget( pConditionDontBranch );
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0)
SetJumpTarget( pCTRDontBranch );
WriteExit(js.compilerPC + 4, 1);
WriteExit(js.compilerPC + 4);
}
void Jit64::bcctrx(UGeckoInstruction inst)
@@ -190,7 +190,7 @@ void Jit64::bcctrx(UGeckoInstruction inst)
WriteExitDestInEAX();
// Would really like to continue the block here, but it ends. TODO.
SetJumpTarget(b);
WriteExit(js.compilerPC + 4, 1);
WriteExit(js.compilerPC + 4);
}
}
@@ -245,5 +245,5 @@ void Jit64::bclrx(UGeckoInstruction inst)
SetJumpTarget( pConditionDontBranch );
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0)
SetJumpTarget( pCTRDontBranch );
WriteExit(js.compilerPC + 4, 1);
WriteExit(js.compilerPC + 4);
}
@@ -85,7 +85,7 @@ void Jit64::fp_tri_op(int d, int a, int b, bool reversible, bool single,
fpr.UnlockAll();
}
void Jit64::fp_arith_s(UGeckoInstruction inst)
void Jit64::fp_arith(UGeckoInstruction inst)
{
INSTRUCTION_START
JITDISABLE(bJITFloatingPointOff)
@@ -106,7 +106,7 @@ void Jit64::fp_arith_s(UGeckoInstruction inst)
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!!!");
}
}
@@ -224,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, d == b, 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)
@@ -400,7 +400,7 @@ void Jit64::cmpXX(UGeckoInstruction inst)
destination = SignExt16(js.next_inst.BD << 2);
else
destination = js.next_compilerPC + SignExt16(js.next_inst.BD << 2);
WriteExit(destination, 0);
WriteExit(destination);
}
else if ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 528)) // bcctrx
{
@@ -424,7 +424,7 @@ void Jit64::cmpXX(UGeckoInstruction inst)
}
else
{
WriteExit(js.next_compilerPC + 4, 0);
WriteExit(js.next_compilerPC + 4);
}
js.cancel = true;
@@ -507,7 +507,7 @@ void Jit64::cmpXX(UGeckoInstruction inst)
destination = SignExt16(js.next_inst.BD << 2);
else
destination = js.next_compilerPC + SignExt16(js.next_inst.BD << 2);
WriteExit(destination, 0);
WriteExit(destination);
}
else if ((js.next_inst.OPCD == 19) && (js.next_inst.SUBOP10 == 528)) // bcctrx
{
@@ -534,7 +534,7 @@ void Jit64::cmpXX(UGeckoInstruction inst)
if (!!(4 & test_bit) == condition) SetJumpTarget(continue2);
if (!!(2 & test_bit) == condition) SetJumpTarget(continue1);
WriteExit(js.next_compilerPC + 4, 1);
WriteExit(js.next_compilerPC + 4);
js.cancel = true;
}
@@ -2221,5 +2221,5 @@ void Jit64::twx(UGeckoInstruction inst)
SetJumpTarget(exit3);
SetJumpTarget(exit4);
SetJumpTarget(exit5);
WriteExit(js.compilerPC + 4, 1);
WriteExit(js.compilerPC + 4);
}
@@ -480,5 +480,5 @@ void Jit64::stmw(UGeckoInstruction inst)
void Jit64::icbi(UGeckoInstruction inst)
{
Default(inst);
WriteExit(js.compilerPC + 4, 0);
WriteExit(js.compilerPC + 4);
}
@@ -137,7 +137,7 @@ void Jit64::mtmsr(UGeckoInstruction inst)
SetJumpTarget(noExceptionsPending);
SetJumpTarget(eeDisabled);
WriteExit(js.compilerPC + 4, 0);
WriteExit(js.compilerPC + 4);
js.firstFPInstructionFound = false;
}
@@ -552,7 +552,8 @@ static void regEmitICmpInst(RegInfo& RI, InstLoc I, CCFlags flag) {
static void regWriteExit(RegInfo& RI, InstLoc dest) {
if (isImm(*dest)) {
RI.Jit->WriteExit(RI.Build->GetImmValue(dest), RI.exitNumber++);
RI.exitNumber++;
RI.Jit->WriteExit(RI.Build->GetImmValue(dest));
} else {
RI.Jit->WriteExitDestInOpArg(regLocForInst(RI, dest));
}
@@ -564,7 +565,7 @@ static bool checkIsSNAN() {
return MathUtil::IsSNAN(isSNANTemp[0][0]) || MathUtil::IsSNAN(isSNANTemp[1][0]);
}
static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit) {
static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit, u32 exitAddress) {
//printf("Writing block: %x\n", js.blockStart);
RegInfo RI(Jit, ibuild->getFirstInst(), ibuild->getNumInsts());
RI.Build = ibuild;
@@ -1791,7 +1792,7 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit) {
Jit->ABI_CallFunction(reinterpret_cast<void *>(&PowerPC::CheckBreakPoints));
Jit->TEST(32, M((void*)PowerPC::GetStatePtr()), Imm32(0xFFFFFFFF));
FixupBranch noBreakpoint = Jit->J_CC(CC_Z);
Jit->WriteExit(InstLoc, 0);
Jit->WriteExit(InstLoc);
Jit->SetJumpTarget(noBreakpoint);
break;
}
@@ -1819,10 +1820,10 @@ static void DoWriteCode(IRBuilder* ibuild, JitIL* Jit) {
}
}
Jit->WriteExit(jit->js.curBlock->exitAddress[0], 0);
Jit->WriteExit(exitAddress);
Jit->UD2();
}
void JitIL::WriteCode() {
DoWriteCode(&ibuild, this);
void JitIL::WriteCode(u32 exitAddress) {
DoWriteCode(&ibuild, this, exitAddress);
}
+11 -7
View File
@@ -381,7 +381,7 @@ void JitIL::Cleanup()
ABI_CallFunctionCCC((void *)&PowerPC::UpdatePerformanceMonitor, js.downcountAmount, jit->js.numLoadStoreInst, jit->js.numFloatingPointInst);
}
void JitIL::WriteExit(u32 destination, int exit_num)
void JitIL::WriteExit(u32 destination)
{
Cleanup();
if (SConfig::GetInstance().m_LocalCoreStartupParameter.bJITILTimeProfiling) {
@@ -391,8 +391,9 @@ void JitIL::WriteExit(u32 destination, int exit_num)
//If nobody has taken care of this yet (this can be removed when all branches are done)
JitBlock *b = js.curBlock;
b->exitAddress[exit_num] = destination;
b->exitPtrs[exit_num] = GetWritableCodePtr();
JitBlock::LinkData linkData;
linkData.exitAddress = destination;
linkData.exitPtrs = GetWritableCodePtr();
// Link opportunity!
int block = blocks.GetBlockNumberFromStartAddress(destination);
@@ -400,13 +401,14 @@ void JitIL::WriteExit(u32 destination, int exit_num)
{
// It exists! Joy of joy!
JMP(blocks.GetBlock(block)->checkedEntry, true);
b->linkStatus[exit_num] = true;
linkData.linkStatus = true;
}
else
{
MOV(32, M(&PC), Imm32(destination));
JMP(asm_routines.dispatcher, true);
}
b->linkData.push_back(linkData);
}
void JitIL::WriteExitDestInOpArg(const Gen::OpArg& arg)
@@ -541,14 +543,16 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
// Analyze the block, collect all instructions it is made of (including inlining,
// if that is enabled), reorder instructions for optimal performance, and join joinable instructions.
b->exitAddress[0] = em_address;
u32 exitAddress = em_address;
u32 merged_addresses[32];
const int capacity_of_merged_addresses = sizeof(merged_addresses) / sizeof(merged_addresses[0]);
int size_of_merged_addresses = 0;
if (!memory_exception)
{
// If there is a memory exception inside a block (broken_block==true), compile up to that instruction.
b->exitAddress[0] = PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, broken_block, code_buf, blockSize, merged_addresses, capacity_of_merged_addresses, size_of_merged_addresses);
// TODO
exitAddress = PPCAnalyst::Flatten(em_address, &size, &js.st, &js.gpa, &js.fpa, broken_block, code_buf, blockSize, merged_addresses, capacity_of_merged_addresses, size_of_merged_addresses);
}
PPCAnalyst::CodeOp *ops = code_buf->codebuffer;
@@ -707,7 +711,7 @@ const u8* JitIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBloc
}
// Perform actual code generation
WriteCode();
WriteCode(exitAddress);
b->codeSize = (u32)(GetCodePtr() - normalEntry);
b->originalSize = size;
+2 -2
View File
@@ -105,7 +105,7 @@ public:
// Utilities for use by opcodes
void WriteExit(u32 destination, int exit_num);
void WriteExit(u32 destination);
void WriteExitDestInOpArg(const Gen::OpArg& arg);
void WriteExceptionExit();
void WriteRfiExitDestInOpArg(const Gen::OpArg& arg);
@@ -121,7 +121,7 @@ public:
void regimmop(int d, int a, bool binary, u32 value, Operation doop, void (Gen::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 (Gen::XEmitter::*op)(Gen::X64Reg, Gen::OpArg));
void WriteCode();
void WriteCode(u32 exitAddress);
// OPCODES
void unknown_instruction(UGeckoInstruction _inst) override;
@@ -186,15 +186,16 @@ void JitArm::WriteExceptionExit()
MOVI2R(A, (u32)asm_routines.testExceptions);
B(A);
}
void JitArm::WriteExit(u32 destination, int exit_num)
void JitArm::WriteExit(u32 destination)
{
Cleanup();
DoDownCount();
//If nobody has taken care of this yet (this can be removed when all branches are done)
JitBlock *b = js.curBlock;
b->exitAddress[exit_num] = destination;
b->exitPtrs[exit_num] = GetWritableCodePtr();
JitBlock::LinkData linkData;
linkData.exitAddress = destination;
linkData.exitPtrs = GetWritableCodePtr();
// Link opportunity!
int block = blocks.GetBlockNumberFromStartAddress(destination);
@@ -202,7 +203,7 @@ void JitArm::WriteExit(u32 destination, int exit_num)
{
// It exists! Joy of joy!
B(blocks.GetBlock(block)->checkedEntry);
b->linkStatus[exit_num] = true;
linkData.linkStatus = true;
}
else
{
@@ -212,6 +213,8 @@ void JitArm::WriteExit(u32 destination, int exit_num)
MOVI2R(A, (u32)asm_routines.dispatcher);
B(A);
}
b->linkData.push_back(linkData);
}
void STACKALIGN JitArm::Run()
@@ -496,7 +499,7 @@ const u8* JitArm::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitBlo
if (broken_block)
{
printf("Broken Block going to 0x%08x\n", nextPC);
WriteExit(nextPC, 0);
WriteExit(nextPC);
}
b->flags = js.block_flags;
+1 -1
View File
@@ -109,7 +109,7 @@ public:
// Utilities for use by opcodes
void WriteExit(u32 destination, int exit_num);
void WriteExit(u32 destination);
void WriteExitDestInR(ARMReg Reg);
void WriteRfiExitDestInR(ARMReg Reg);
void WriteExceptionExit();
@@ -135,9 +135,11 @@ void JitArm::bx(UGeckoInstruction inst)
else
destination = js.compilerPC + SignExt26(inst.LI << 2);
#ifdef ACID_TEST
// TODO: Not implemented yet.
//if (inst.LK)
//AND(32, M(&PowerPC::ppcState.cr), Imm32(~(0xFF000000)));
if (inst.LK)
{
MOV(R14, 0);
STRB(R14, R9, PPCSTATE_OFF(cr_fast[0]));
}
#endif
if (destination == js.compilerPC)
{
@@ -152,7 +154,7 @@ void JitArm::bx(UGeckoInstruction inst)
MOVI2R(R14, (u32)asm_routines.testExceptions);
B(R14);
}
WriteExit(destination, 0);
WriteExit(destination);
}
void JitArm::bcx(UGeckoInstruction inst)
@@ -207,14 +209,14 @@ void JitArm::bcx(UGeckoInstruction inst)
destination = SignExt16(inst.BD << 2);
else
destination = js.compilerPC + SignExt16(inst.BD << 2);
WriteExit(destination, 0);
WriteExit(destination);
if ((inst.BO & BO_DONT_CHECK_CONDITION) == 0)
SetJumpTarget( pConditionDontBranch );
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0)
SetJumpTarget( pCTRDontBranch );
WriteExit(js.compilerPC + 4, 1);
WriteExit(js.compilerPC + 4);
}
void JitArm::bcctrx(UGeckoInstruction inst)
{
@@ -276,7 +278,7 @@ void JitArm::bcctrx(UGeckoInstruction inst)
WriteExitDestInR(rA);
SetJumpTarget(b);
WriteExit(js.compilerPC + 4, 1);
WriteExit(js.compilerPC + 4);
}
}
void JitArm::bclrx(UGeckoInstruction inst)
@@ -329,8 +331,11 @@ void JitArm::bclrx(UGeckoInstruction inst)
// This below line can be used to prove that blr "eats flags" in practice.
// This observation will let us do a lot of fun observations.
#ifdef ACID_TEST
// TODO: Not yet implemented
// AND(32, M(&PowerPC::ppcState.cr), Imm32(~(0xFF000000)));
if (inst.LK)
{
MOV(R14, 0);
STRB(R14, R9, PPCSTATE_OFF(cr_fast[0]));
}
#endif
//MOV(32, R(EAX), M(&LR));
@@ -350,5 +355,5 @@ void JitArm::bclrx(UGeckoInstruction inst)
SetJumpTarget( pConditionDontBranch );
if ((inst.BO & BO_DONT_DECREMENT_FLAG) == 0)
SetJumpTarget( pCTRDontBranch );
WriteExit(js.compilerPC + 4, 1);
WriteExit(js.compilerPC + 4);
}
@@ -531,6 +531,6 @@ void JitArm::dcbst(UGeckoInstruction inst)
void JitArm::icbi(UGeckoInstruction inst)
{
Default(inst);
WriteExit(js.compilerPC + 4, 0);
WriteExit(js.compilerPC + 4);
}
@@ -205,7 +205,7 @@ void JitArm::mtmsr(UGeckoInstruction inst)
gpr.Flush();
fpr.Flush();
WriteExit(js.compilerPC + 4, 0);
WriteExit(js.compilerPC + 4);
}
void JitArm::mfmsr(UGeckoInstruction inst)
@@ -156,7 +156,8 @@ static ARMReg regEnsureInReg(RegInfo& RI, InstLoc I) {
static void regWriteExit(RegInfo& RI, InstLoc dest) {
if (isImm(*dest)) {
RI.Jit->WriteExit(RI.Build->GetImmValue(dest), RI.exitNumber++);
RI.exitNumber++;
RI.Jit->WriteExit(RI.Build->GetImmValue(dest));
} else {
RI.Jit->WriteExitDestInReg(regLocForInst(RI, dest));
}
@@ -281,7 +282,7 @@ static void regEmitCmp(RegInfo& RI, InstLoc I) {
}
}
static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit) {
static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit, u32 exitAddress) {
RegInfo RI(Jit, ibuild->getFirstInst(), ibuild->getNumInsts());
RI.Build = ibuild;
@@ -733,10 +734,10 @@ static void DoWriteCode(IRBuilder* ibuild, JitArmIL* Jit) {
}
}
Jit->WriteExit(jit->js.curBlock->exitAddress[0], 0);
Jit->WriteExit(exitAddress);
Jit->BKPT(0x111);
}
void JitArmIL::WriteCode() {
DoWriteCode(&ibuild, this);
void JitArmIL::WriteCode(u32 exitAddress) {
DoWriteCode(&ibuild, this, exitAddress);
}
@@ -117,13 +117,14 @@ void JitArmIL::WriteExceptionExit()
MOVI2R(R14, (u32)asm_routines.testExceptions);
B(R14);
}
void JitArmIL::WriteExit(u32 destination, int exit_num)
void JitArmIL::WriteExit(u32 destination)
{
DoDownCount();
//If nobody has taken care of this yet (this can be removed when all branches are done)
JitBlock *b = js.curBlock;
b->exitAddress[exit_num] = destination;
b->exitPtrs[exit_num] = GetWritableCodePtr();
JitBlock::LinkData linkData;
linkData.exitAddress = destination;
linkData.exitPtrs = GetWritableCodePtr();
// Link opportunity!
int block = blocks.GetBlockNumberFromStartAddress(destination);
@@ -131,7 +132,7 @@ void JitArmIL::WriteExit(u32 destination, int exit_num)
{
// It exists! Joy of joy!
B(blocks.GetBlock(block)->checkedEntry);
b->linkStatus[exit_num] = true;
linkData.linkStatus = true;
}
else
{
@@ -140,6 +141,8 @@ void JitArmIL::WriteExit(u32 destination, int exit_num)
MOVI2R(R14, (u32)asm_routines.dispatcher);
B(R14);
}
b->linkData.push_back(linkData);
}
void JitArmIL::PrintDebug(UGeckoInstruction inst, u32 level)
{
@@ -347,12 +350,12 @@ const u8* JitArmIL::DoJit(u32 em_address, PPCAnalyst::CodeBuffer *code_buf, JitB
if (broken_block)
{
printf("Broken Block going to 0x%08x\n", nextPC);
WriteExit(nextPC, 0);
WriteExit(nextPC);
}
// Perform actual code generation
WriteCode();
WriteCode(nextPC);
b->flags = js.block_flags;
b->codeSize = (u32)(GetCodePtr() - normalEntry);
b->originalSize = size;
@@ -64,8 +64,8 @@ public:
void Run();
void SingleStep();
//
void WriteCode();
void WriteExit(u32 destination, int exit_num);
void WriteCode(u32 exitAddress);
void WriteExit(u32 destination);
void WriteExitDestInReg(ARMReg Reg);
void WriteRfiExitDestInR(ARMReg Reg);
void WriteExceptionExit();
@@ -234,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
@@ -35,8 +35,6 @@ op_agent_t agent;
using namespace Gen;
#define INVALID_EXIT 0xFFFFFFFF
bool JitBaseBlockCache::IsFull() const
{
return GetNumBlocks() >= MAX_NUM_BLOCKS - 1;
@@ -167,12 +165,6 @@ using namespace Gen;
JitBlock &b = blocks[num_blocks];
b.invalid = false;
b.originalAddress = em_address;
b.exitAddress[0] = INVALID_EXIT;
b.exitAddress[1] = INVALID_EXIT;
b.exitPtrs[0] = 0;
b.exitPtrs[1] = 0;
b.linkStatus[0] = false;
b.linkStatus[1] = false;
num_blocks++; //commit the current block
return num_blocks - 1;
}
@@ -193,10 +185,9 @@ using namespace Gen;
block_map[std::make_pair(pAddr + 4 * b.originalSize - 1, pAddr)] = block_num;
if (block_link)
{
for (int i = 0; i < 2; i++)
for (const auto& e : b.linkData)
{
if (b.exitAddress[i] != INVALID_EXIT)
links_to.insert(std::pair<u32, int>(b.exitAddress[i], block_num));
links_to.insert(std::pair<u32, int>(e.exitAddress, block_num));
}
LinkBlock(block_num);
@@ -275,15 +266,15 @@ using namespace Gen;
// This block is dead. Don't relink it.
return;
}
for (int e = 0; e < 2; e++)
for (auto& e : b.linkData)
{
if (b.exitAddress[e] != INVALID_EXIT && !b.linkStatus[e])
if (!e.linkStatus)
{
int destinationBlock = GetBlockNumberFromStartAddress(b.exitAddress[e]);
int destinationBlock = GetBlockNumberFromStartAddress(e.exitAddress);
if (destinationBlock != -1)
{
WriteLinkBlock(b.exitPtrs[e], blocks[destinationBlock].checkedEntry);
b.linkStatus[e] = true;
WriteLinkBlock(e.exitPtrs, blocks[destinationBlock].checkedEntry);
e.linkStatus = true;
}
}
}
@@ -316,10 +307,10 @@ using namespace Gen;
return;
for (multimap<u32, int>::iterator iter = ppp.first; iter != ppp.second; ++iter) {
JitBlock &sourceBlock = blocks[iter->second];
for (int e = 0; e < 2; e++)
for (auto& e : sourceBlock.linkData)
{
if (sourceBlock.exitAddress[e] == b.originalAddress)
sourceBlock.linkStatus[e] = false;
if (e.exitAddress == b.originalAddress)
e.linkStatus = false;
}
}
}
@@ -35,9 +35,6 @@ struct JitBlock
const u8 *checkedEntry;
const u8 *normalEntry;
u8 *exitPtrs[2]; // to be able to rewrite the exit jum
u32 exitAddress[2]; // 0xFFFFFFFF == unknown
u32 originalAddress;
u32 codeSize;
u32 originalSize;
@@ -45,7 +42,13 @@ struct JitBlock
int flags;
bool invalid;
bool linkStatus[2];
struct LinkData {
u8 *exitPtrs; // to be able to rewrite the exit jum
u32 exitAddress;
bool linkStatus; // is it already linked?
};
std::vector<LinkData> linkData;
#ifdef _WIN32
// we don't really need to save start and stop
@@ -323,7 +323,7 @@ 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_LOADSTORE_NO_PROLOG;
bool noProlog = (0 != (flags & SAFE_LOADSTORE_NO_PROLOG));
bool swap = !(flags & SAFE_LOADSTORE_NO_SWAP);
ABI_PushRegistersAndAdjustStack(registersInUse, noProlog);
switch (accessSize)
+35 -34
View File
@@ -14,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)
{
@@ -182,26 +173,34 @@ void CountInstruction(UGeckoInstruction _inst)
{
GekkoOPInfo *info = GetOpInfo(_inst);
if (info)
{
info->runCount++;
}
}
void PrintInstructionRunCounts()
{
std::vector<op_inf> temp;
for (int i = 0; i < m_numInstructions; i++)
typedef std::pair<const char*, u64> OpInfo;
std::vector<OpInfo> 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);
}
}
@@ -212,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%" PRId64 "\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%" PRId64 "\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);
}
}
+6 -2
View File
@@ -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");
+12
View File
@@ -282,10 +282,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;
@@ -154,12 +154,13 @@ Joystick::~Joystick()
{
// stop/destroy all effects
SDL_HapticStopAll(m_haptic);
std::list<EffectIDState>::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<EffectIDState>::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
@@ -5,138 +5,12 @@
#include "D3DBase.h"
#include "D3DTexture.h"
#include <atlbase.h>
#include <wincodec.h>
#include <wincodecsdk.h>
#pragma comment(lib, "WindowsCodecs.lib")
namespace DX11
{
namespace D3D
{
HRESULT TextureToPng(D3D11_MAPPED_SUBRESOURCE &map, LPCWSTR wzFilename, int width, int height, bool saveAlpha)
{
IWICImagingFactory *piFactory = NULL;
IWICBitmapEncoder *piEncoder = NULL;
IWICBitmapFrameEncode *piBitmapFrame = NULL;
IPropertyBag2 *pPropertybag = NULL;
IWICStream *piStream = NULL;
HRESULT hr = CoCreateInstance(
CLSID_WICImagingFactory,
NULL,
CLSCTX_INPROC_SERVER,
IID_IWICImagingFactory,
(LPVOID*)&piFactory);
if (SUCCEEDED(hr))
{
hr = piFactory->CreateStream(&piStream);
}
if (SUCCEEDED(hr))
{
hr = piStream->InitializeFromFilename(wzFilename, GENERIC_WRITE);
}
if (SUCCEEDED(hr))
{
hr = piFactory->CreateEncoder(GUID_ContainerFormatPng, NULL, &piEncoder);
}
if (SUCCEEDED(hr))
{
hr = piEncoder->Initialize(piStream, WICBitmapEncoderNoCache);
}
if (SUCCEEDED(hr))
{
hr = piEncoder->CreateNewFrame(&piBitmapFrame, &pPropertybag);
}
if (SUCCEEDED(hr))
{
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->Initialize(pPropertybag);
}
}
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->SetSize(width, height);
}
WICPixelFormatGUID formatGUID = GUID_WICPixelFormat32bppBGRA;
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->SetPixelFormat(&formatGUID);
}
if (SUCCEEDED(hr))
{
// We're expecting to write out 32bppBGRA. Fail if the encoder cannot do it.
hr = IsEqualGUID(formatGUID, GUID_WICPixelFormat32bppBGRA) ? S_OK : E_FAIL;
}
if (SUCCEEDED(hr))
{
if (map.pData != NULL)
{
for (int y = 0; y < height; ++y)
{
u8* ptr = (u8*)map.pData + y * map.RowPitch;
for (unsigned int x = 0; x < map.RowPitch/4; ++x)
{
u8 r = ptr[0];
u8 g = ptr[1];
u8 b = ptr[2];
ptr[0] = b;
ptr[1] = g;
ptr[2] = r;
if (!saveAlpha)
ptr[3] = 0xff;
ptr += 4;
}
}
hr = piBitmapFrame->WritePixels(height, map.RowPitch, height * map.RowPitch, (BYTE*)map.pData);
}
else
{
hr = E_OUTOFMEMORY;
}
}
if (SUCCEEDED(hr))
{
hr = piBitmapFrame->Commit();
}
if (SUCCEEDED(hr))
{
hr = piEncoder->Commit();
}
if (piFactory)
piFactory->Release();
if (piBitmapFrame)
piBitmapFrame->Release();
if (piEncoder)
piEncoder->Release();
if (piStream)
piStream->Release();
return hr;
}
void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage)
{
if (usage == D3D11_USAGE_DYNAMIC || usage == D3D11_USAGE_STAGING)
@@ -11,7 +11,6 @@ namespace DX11
namespace D3D
{
HRESULT TextureToPng(D3D11_MAPPED_SUBRESOURCE& map, LPCWSTR wzFilename, int width, int height, bool saveAlpha = true);
void ReplaceRGBATexture2D(ID3D11Texture2D* pTexture, const u8* buffer, unsigned int width, unsigned int height, unsigned int pitch, unsigned int level, D3D11_USAGE usage);
}
@@ -180,7 +180,7 @@ void FramebufferManager::GetTargetSize(unsigned int *width, unsigned int *height
}
void XFBSource::Draw(const MathUtil::Rectangle<float> &sourcerc,
const MathUtil::Rectangle<float> &drawrc, int width, int height) const
const MathUtil::Rectangle<float> &drawrc) const
{
D3D::drawShadedTexSubQuad(tex->GetSRV(), &sourcerc,
texWidth, texHeight, &drawrc, PixelShaderCache::GetColorCopyProgram(false),
@@ -51,7 +51,7 @@ struct XFBSource : public XFBSourceBase
~XFBSource() { tex->Release(); }
void Draw(const MathUtil::Rectangle<float> &sourcerc,
const MathUtil::Rectangle<float> &drawrc, int width, int height) const;
const MathUtil::Rectangle<float> &drawrc) const;
void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight);
void CopyEFB(float Gamma);
+7 -5
View File
@@ -34,6 +34,7 @@
#include "FPSCounter.h"
#include "ConfigManager.h"
#include <strsafe.h>
#include "ImageWrite.h"
namespace DX11
{
@@ -693,11 +694,12 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle
D3D11_MAPPED_SUBRESOURCE map;
D3D::context->Map(s_screenshot_texture, 0, D3D11_MAP_READ_WRITE, 0, &map);
// ready to be saved
HRESULT hr = D3D::TextureToPng(map, UTF8ToUTF16(filename.c_str()).c_str(), rc.GetWidth(), rc.GetHeight(), false);
bool saved_png = TextureToPng((u8*)map.pData, map.RowPitch, filename, rc.GetWidth(), rc.GetHeight(), false);
D3D::context->Unmap(s_screenshot_texture, 0);
if (SUCCEEDED(hr))
if (saved_png)
{
OSD::AddMessage(StringFromFormat("Saved %i x %i %s", rc.GetWidth(),
rc.GetHeight(), filename.c_str()));
@@ -707,7 +709,7 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle
OSD::AddMessage(StringFromFormat("Error saving %s", filename.c_str()));
}
return SUCCEEDED(hr);
return saved_png;
}
void formatBufferDump(const u8* in, u8* out, int w, int h, int p)
@@ -830,7 +832,7 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r
//drawRc.right *= hScale;
}
xfbSource->Draw(sourceRc, drawRc, 0, 0);
xfbSource->Draw(sourceRc, drawRc);
}
}
else
@@ -14,12 +14,13 @@
#include "PSTextureEncoder.h"
#include "HW/Memmap.h"
#include "VideoConfig.h"
#include "ImageWrite.h"
namespace DX11
{
static TextureEncoder* g_encoder = NULL;
const size_t MAX_COPY_BUFFERS = 25;
const size_t MAX_COPY_BUFFERS = 32;
ID3D11Buffer* efbcopycbuf[MAX_COPY_BUFFERS] = { 0 };
TextureCache::TCacheEntry::~TCacheEntry()
@@ -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;
@@ -54,6 +55,8 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level)
HRESULT hr = D3D::device->CreateTexture2D(&desc, NULL, &pNewTexture);
bool saved_png = false;
if (SUCCEEDED(hr) && pNewTexture)
{
D3D::context->CopyResource(pNewTexture, pSurface);
@@ -62,13 +65,13 @@ bool TextureCache::TCacheEntry::Save(const char filename[], unsigned int level)
HRESULT hr = D3D::context->Map(pNewTexture, 0, D3D11_MAP_READ_WRITE, 0, &map);
if (SUCCEEDED(hr))
{
hr = D3D::TextureToPng(map, UTF8ToUTF16(filename).c_str(), desc.Width, desc.Height);
saved_png = TextureToPng((u8*)map.pData, map.RowPitch, filename, desc.Width, desc.Height);
D3D::context->Unmap(pNewTexture, 0);
}
SAFE_RELEASE(pNewTexture);
}
return SUCCEEDED(hr);
return saved_png;
}
void TextureCache::TCacheEntry::Load(unsigned int width, unsigned int height,
@@ -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,
@@ -66,15 +66,6 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
// alpha channel should be ignored if the EFB does not have one.
// Create EFB target.
u32 depthType;
if (DriverDetails::HasBug(DriverDetails::BUG_ISTEGRA))
{
depthType = GL_DEPTH_COMPONENT;
}
else
{
depthType = GL_DEPTH_COMPONENT24;
}
glGenFramebuffers(1, &m_efbFramebuffer);
glActiveTexture(GL_TEXTURE0 + 9);
@@ -94,7 +85,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
glBindTexture(getFbType(), m_efbDepth);
glTexParameteri(getFbType(), GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(getFbType(), 0, depthType, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
glTexImage2D(getFbType(), 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
glBindTexture(getFbType(), m_resolvedColorTexture);
glTexParameteri(getFbType(), GL_TEXTURE_MAX_LEVEL, 0);
@@ -159,7 +150,7 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
glBindTexture(getFbType(), m_resolvedDepthTexture);
glTexParameteri(getFbType(), GL_TEXTURE_MAX_LEVEL, 0);
glTexImage2D(getFbType(), 0, depthType, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
glTexImage2D(getFbType(), 0, GL_DEPTH_COMPONENT24, m_targetWidth, m_targetHeight, 0, GL_DEPTH_COMPONENT, GL_UNSIGNED_INT, NULL);
// Bind resolved textures to resolved framebuffer.
@@ -235,13 +226,8 @@ FramebufferManager::FramebufferManager(int targetWidth, int targetHeight, int ms
" ocol0 = float4(dst6) / 63.f;\n"
"}";
if(g_ogl_config.eSupportedGLSLVersion != GLSLES2)
{
// HACK: This shaders aren't glsles2 compatible as glsles2 don't support bit operations
// it could be workaround by floor + frac + tons off additions, but I think it isn't worth
ProgramShaderCache::CompileShader(m_pixel_format_shaders[0], vs, ps_rgb8_to_rgba6);
ProgramShaderCache::CompileShader(m_pixel_format_shaders[1], vs, ps_rgba6_to_rgb8);
}
ProgramShaderCache::CompileShader(m_pixel_format_shaders[0], vs, ps_rgb8_to_rgba6);
ProgramShaderCache::CompileShader(m_pixel_format_shaders[1], vs, ps_rgba6_to_rgb8);
}
FramebufferManager::~FramebufferManager()
@@ -372,19 +358,6 @@ GLuint FramebufferManager::ResolveAndGetDepthTarget(const EFBRectangle &source_r
void FramebufferManager::ReinterpretPixelData(unsigned int convtype)
{
if(g_ogl_config.eSupportedGLSLVersion == GLSLES2) {
// This feature isn't supported by glsles2
// TODO: move this to InitBackendInfo
// We have to disable both the active and the stored config. Else we
// would either
// show this line per format change in one frame or
// once per frame.
OSD::AddMessage("Format Change Emulation isn't supported by your GPU.", 10000);
g_ActiveConfig.bEFBEmulateFormatChanges = false;
g_Config.bEFBEmulateFormatChanges = false;
return;
}
g_renderer->ResetAPIState();
GLuint src_texture = 0;
@@ -433,7 +406,7 @@ XFBSource::~XFBSource()
void XFBSource::Draw(const MathUtil::Rectangle<float> &sourcerc,
const MathUtil::Rectangle<float> &drawrc, int width, int height) const
const MathUtil::Rectangle<float> &drawrc) const
{
// Texture map xfbSource->texture onto the main buffer
glFramebufferTexture2D(GL_READ_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_TEXTURE_2D, texture, 0);
@@ -52,7 +52,7 @@ struct XFBSource : public XFBSourceBase
void CopyEFB(float Gamma) override;
void DecodeToTexture(u32 xfbAddr, u32 fbWidth, u32 fbHeight) override;
void Draw(const MathUtil::Rectangle<float> &sourcerc,
const MathUtil::Rectangle<float> &drawrc, int width, int height) const override;
const MathUtil::Rectangle<float> &drawrc) const override;
const GLuint texture;
};
@@ -72,67 +72,42 @@ namespace GLFunc
self = dlopen(NULL, RTLD_LAZY);
LoadFunction("glUnmapBuffer", (void**)&glUnmapBuffer);
LoadFunction("glBeginQuery", (void**)&glBeginQuery);
LoadFunction("glEndQuery", (void**)&glEndQuery);
LoadFunction("glGetQueryObjectuiv", (void**)&glGetQueryObjectuiv);
LoadFunction("glDeleteQueries", (void**)&glDeleteQueries);
LoadFunction("glGenQueries", (void**)&glGenQueries);
if (DriverDetails::HasBug(DriverDetails::BUG_ISTEGRA))
{
LoadFunction("glBeginQueryEXT", (void**)&glBeginQuery);
LoadFunction("glEndQueryEXT", (void**)&glEndQuery);
LoadFunction("glGetQueryObjectuivEXT", (void**)&glGetQueryObjectuiv);
LoadFunction("glDeleteQueriesEXT", (void**)&glDeleteQueries);
LoadFunction("glGenQueriesEXT", (void**)&glGenQueries);
LoadFunction("glMapBufferRange", (void**)&glMapBufferRange);
LoadFunction("glBindBufferRange", (void**)&glBindBufferRange);
LoadFunction("glBlitFramebuffer", (void**)&glBlitFramebuffer);
LoadFunction("glMapBufferRangeNV", (void**)&glMapBufferRange);
LoadFunction("glBindBufferRangeNV", (void**)&glBindBufferRange);
LoadFunction("glBlitFramebufferNV", (void**)&glBlitFramebuffer);
LoadFunction("glGenVertexArrays", (void**)&glGenVertexArrays);
LoadFunction("glDeleteVertexArrays", (void**)&glDeleteVertexArrays);
LoadFunction("glBindVertexArray", (void**)&glBindVertexArray);
LoadFunction("glGenVertexArraysOES", (void**)&glGenVertexArrays);
LoadFunction("glDeleteVertexArraysOES", (void**)&glDeleteVertexArrays);
LoadFunction("glBindVertexArrayOES", (void**)&glBindVertexArray);
LoadFunction("glClientWaitSync", (void**)&glClientWaitSync);
LoadFunction("glDeleteSync", (void**)&glDeleteSync);
LoadFunction("glFenceSync", (void**)&glFenceSync);
LoadFunction("glRenderbufferStorageMultisampleNV", (void**)&glRenderbufferStorageMultisample);
LoadFunction("glSamplerParameterf", (void**)&glSamplerParameterf);
LoadFunction("glSamplerParameteri", (void**)&glSamplerParameteri);
LoadFunction("glSamplerParameterfv", (void**)&glSamplerParameterfv);
LoadFunction("glBindSampler", (void**)&glBindSampler);
LoadFunction("glDeleteSamplers", (void**)&glDeleteSamplers);
LoadFunction("glGenSamplers", (void**)&glGenSamplers);
LoadFunction("glGetUniformBlockIndexNV", (void**)&glGetUniformBlockIndex);
LoadFunction("glUniformBlockBindingNV", (void**)&glUniformBlockBinding);
}
else
{
LoadFunction("glBeginQuery", (void**)&glBeginQuery);
LoadFunction("glEndQuery", (void**)&glEndQuery);
LoadFunction("glGetQueryObjectuiv", (void**)&glGetQueryObjectuiv);
LoadFunction("glDeleteQueries", (void**)&glDeleteQueries);
LoadFunction("glGenQueries", (void**)&glGenQueries);
LoadFunction("glGetProgramBinary", (void**)&glGetProgramBinary);
LoadFunction("glProgramBinary", (void**)&glProgramBinary);
LoadFunction("glProgramParameteri", (void**)&glProgramParameteri);
LoadFunction("glMapBufferRange", (void**)&glMapBufferRange);
LoadFunction("glBindBufferRange", (void**)&glBindBufferRange);
LoadFunction("glBlitFramebuffer", (void**)&glBlitFramebuffer);
LoadFunction("glDrawRangeElements", (void**)&glDrawRangeElements);
LoadFunction("glGenVertexArrays", (void**)&glGenVertexArrays);
LoadFunction("glDeleteVertexArrays", (void**)&glDeleteVertexArrays);
LoadFunction("glBindVertexArray", (void**)&glBindVertexArray);
LoadFunction("glRenderbufferStorageMultisample", (void**)&glRenderbufferStorageMultisample);
LoadFunction("glClientWaitSync", (void**)&glClientWaitSync);
LoadFunction("glDeleteSync", (void**)&glDeleteSync);
LoadFunction("glFenceSync", (void**)&glFenceSync);
LoadFunction("glGetUniformBlockIndex", (void**)&glGetUniformBlockIndex);
LoadFunction("glUniformBlockBinding", (void**)&glUniformBlockBinding);
LoadFunction("glSamplerParameterf", (void**)&glSamplerParameterf);
LoadFunction("glSamplerParameteri", (void**)&glSamplerParameteri);
LoadFunction("glSamplerParameterfv", (void**)&glSamplerParameterfv);
LoadFunction("glBindSampler", (void**)&glBindSampler);
LoadFunction("glDeleteSamplers", (void**)&glDeleteSamplers);
LoadFunction("glGenSamplers", (void**)&glGenSamplers);
LoadFunction("glGetProgramBinary", (void**)&glGetProgramBinary);
LoadFunction("glProgramBinary", (void**)&glProgramBinary);
LoadFunction("glProgramParameteri", (void**)&glProgramParameteri);
LoadFunction("glDrawRangeElements", (void**)&glDrawRangeElements);
LoadFunction("glRenderbufferStorageMultisample", (void**)&glRenderbufferStorageMultisample);
LoadFunction("glGetUniformBlockIndex", (void**)&glGetUniformBlockIndex);
LoadFunction("glUniformBlockBinding", (void**)&glUniformBlockBinding);
}
dlclose(self);
}
}
@@ -571,12 +571,12 @@ void ProgramShaderCache::CreateHeader ( void )
"%s\n" // ubo
"%s\n" // early-z
// Precision defines for GLSLES2/3
// Precision defines for GLSLES3
"%s\n"
"\n"// A few required defines and ones that will make our lives a lot easier
"#define ATTRIN %s\n"
"#define ATTROUT %s\n"
"#define ATTRIN in\n"
"#define ATTROUT out\n"
"#define VARYIN %s\n"
"#define VARYOUT %s\n"
@@ -594,40 +594,18 @@ void ProgramShaderCache::CreateHeader ( void )
"%s\n"
"%s\n"
// GLSLES2 hacks
"%s\n"
"%s\n"
"%s\n"
"%s\n"
"%s\n"
"%s\n"
"%s\n"
"#define COLOROUT(name) %s\n"
, v==GLSLES2 ? "" : v==GLSLES3 ? "#version 300 es" : v==GLSL_130 ? "#version 130" : v==GLSL_140 ? "#version 140" : "#version 150"
, v==GLSLES3 ? "#version 300 es" : v==GLSL_130 ? "#version 130" : v==GLSL_140 ? "#version 140" : "#version 150"
, g_ActiveConfig.backend_info.bSupportsGLSLUBO && v<GLSL_140 ? "#extension GL_ARB_uniform_buffer_object : enable" : ""
, g_ActiveConfig.backend_info.bSupportsEarlyZ ? "#extension GL_ARB_shader_image_load_store : enable" : ""
, (v==GLSLES3 || v==GLSLES2) ? "precision highp float;" : ""
, v==GLSLES3 ? "precision highp float;" : ""
, v==GLSLES2 ? "attribute" : "in"
, v==GLSLES2 ? "attribute" : "out"
, v==GLSLES2 ? "varying" : DriverDetails::HasBug(DriverDetails::BUG_BROKENCENTROID) ? "in" : "centroid in"
, v==GLSLES2 ? "varying" : DriverDetails::HasBug(DriverDetails::BUG_BROKENCENTROID) ? "out" : "centroid out"
, DriverDetails::HasBug(DriverDetails::BUG_BROKENCENTROID) ? "in" : "centroid in"
, DriverDetails::HasBug(DriverDetails::BUG_BROKENCENTROID) ? "out" : "centroid out"
, v==GLSLES2 ? "#define texture2DRect texture2D" : v==GLSLES3 ? "" : v<=GLSL_130 ? "#extension GL_ARB_texture_rectangle : enable" : "#define texture2DRect texture"
, v==GLSLES3 ? "" : v<=GLSL_130 ? "#extension GL_ARB_texture_rectangle : enable" : "#define texture2DRect texture"
, v==GLSLES3 ? "#define texture2DRect(samp, uv) texelFetch(samp, ivec2(floor(uv)), 0)" : ""
, (v==GLSLES3 || v==GLSLES2) ? "#define sampler2DRect sampler2D" : ""
, v==GLSLES2 ? "#define texture texture2D" : ""
, v==GLSLES2 ? "#define round(x) floor((x)+0.5)" : ""
, v==GLSLES2 ? "#define out " : ""
, v==GLSLES2 ? "#define ocol0 gl_FragColor" : ""
, v==GLSLES2 ? "#define ocol1 gl_FragColor" : ""
, DriverDetails::HasBug(DriverDetails::BUG_ISTEGRA) ? "#extension GL_NV_uniform_buffer_object : enable" : ""
, DriverDetails::HasBug(DriverDetails::BUG_ISTEGRA) ? "#extension GL_NV_fragdepth : enable" : ""
, v==GLSLES2 ? "" : "out vec4 name;"
, v==GLSLES3 ? "#define sampler2DRect sampler2D" : ""
);
}
@@ -144,7 +144,7 @@ RasterFont::RasterFont()
for(u32 y=0; y<char_height; y++) {
for(u32 c=0; c<char_count; c++) {
for(u32 x=0; x<char_width; x++) {
bool pixel = rasters[c][y] & (1<<(char_width-x-1));
bool pixel = (0 != (rasters[c][y] & (1<<(char_width-x-1))));
texture_data[char_width*char_count*y+char_width*c+x] = pixel ? -1 : 0;
}
}
+31 -116
View File
@@ -63,10 +63,6 @@
#include "AVIDump.h"
#endif
#if defined(HAVE_WX) && HAVE_WX
#include <wx/image.h>
#endif
// glew1.8 doesn't define KHR_debug
#ifndef GL_DEBUG_OUTPUT
#define GL_DEBUG_OUTPUT 0x92E0
@@ -78,18 +74,6 @@ void VideoConfig::UpdateProjectionHack()
::UpdateProjectionHack(g_Config.iPhackvalue, g_Config.sPhackvalue);
}
#if defined(HAVE_WX) && HAVE_WX
// Screenshot thread struct
typedef struct
{
int W, H;
std::string filename;
wxImage *img;
} ScrStrct;
#endif
int OSDInternalW, OSDInternalH;
namespace OGL
@@ -387,10 +371,7 @@ Renderer::Renderer()
g_ogl_config.bSupportSampleShading = false;
g_ogl_config.bSupportOGL31 = false;
g_ogl_config.bSupportViewportFloat = false;
if (DriverDetails::HasBug(DriverDetails::BUG_ISTEGRA) || DriverDetails::HasBug(DriverDetails::BUG_ISPOWERVR))
g_ogl_config.eSupportedGLSLVersion = GLSLES2;
else
g_ogl_config.eSupportedGLSLVersion = GLSLES3;
g_ogl_config.eSupportedGLSLVersion = GLSLES3;
#else
#ifdef __APPLE__
glewExperimental = 1;
@@ -485,19 +466,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"))
{
@@ -1391,7 +1376,7 @@ void Renderer::Swap(u32 xfbAddr, u32 fbWidth, u32 fbHeight,const EFBRectangle& r
sourceRc.top = xfbSource->sourceRc.top;
sourceRc.bottom = xfbSource->sourceRc.bottom;
xfbSource->Draw(sourceRc, drawRc, 0, 0);
xfbSource->Draw(sourceRc, drawRc);
}
}
else
@@ -1639,7 +1624,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;
@@ -1800,69 +1785,21 @@ 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)
{
// Flip image upside down. Damn OpenGL.
for (int y = 0; y < h / 2; y++)
for (int y = 0; y < h / 2; ++y)
{
for(int x = 0; x < w; x++)
for(int x = 0; x < w; ++x)
{
std::swap(data[(y * w + x) * 3], data[((h - 1 - y) * w + x) * 3]);
std::swap(data[(y * w + x) * 3 + 1], data[((h - 1 - y) * w + x) * 3 + 1]);
std::swap(data[(y * w + x) * 3 + 2], data[((h - 1 - y) * w + x) * 3 + 2]);
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]);
}
}
}
}
// TODO: remove
extern bool g_aspect_wide;
#if defined(HAVE_WX) && HAVE_WX
void TakeScreenshot(ScrStrct* threadStruct)
{
// These will contain the final image size
float FloatW = (float)threadStruct->W;
float FloatH = (float)threadStruct->H;
// 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
threadStruct->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
threadStruct->img->SaveFile(StrToWxStr(threadStruct->filename),
wxBITMAP_TYPE_PNG);
threadStruct->img->Destroy();
// Show success messages
OSD::AddMessage(StringFromFormat("Saved %i x %i %s", (int)FloatW, (int)FloatH,
threadStruct->filename.c_str()), 2000);
delete threadStruct;
}
#endif
namespace OGL
{
@@ -1870,48 +1807,26 @@ bool Renderer::SaveScreenshot(const std::string &filename, const TargetRectangle
{
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 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;
#if defined(HAVE_WX) && HAVE_WX
// Create wxImage
wxImage *a = new wxImage(W, H, data);
return success;
if (scrshotThread.joinable())
scrshotThread.join();
ScrStrct *threadStruct = new ScrStrct;
threadStruct->filename = filename;
threadStruct->img = a;
threadStruct->H = H; threadStruct->W = W;
scrshotThread = std::thread(TakeScreenshot, threadStruct);
#ifdef _WIN32
SetThreadPriority(scrshotThread.native_handle(), THREAD_PRIORITY_BELOW_NORMAL);
#endif
bool result = true;
OSD::AddMessage("Saving Screenshot... ", 2000);
#else
bool result = SaveTGA(filename.c_str(), W, H, data);
free(data);
#endif
return result;
}
}
+1 -2
View File
@@ -13,7 +13,6 @@ enum GLSL_VERSION {
GLSL_130,
GLSL_140,
GLSL_150, // and above
GLSLES2,
GLSLES3
};
@@ -63,7 +62,7 @@ public:
void RenderText(const char* pstr, int left, int top, u32 color) override;
void DrawDebugInfo();
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;
@@ -16,14 +16,11 @@ SamplerCache::SamplerCache()
SamplerCache::~SamplerCache()
{
if (!DriverDetails::HasBug(DriverDetails::BUG_ISTEGRA))
Clear();
Clear();
}
void SamplerCache::SetSamplerState(int stage, const TexMode0& tm0, const TexMode1& tm1)
{
if (DriverDetails::HasBug(DriverDetails::BUG_ISTEGRA))
return;
// TODO: can this go somewhere else?
if (m_last_max_anisotropy != g_ActiveConfig.iMaxAnisotropy)
{
@@ -40,7 +40,7 @@ StreamBuffer::StreamBuffer(u32 type, size_t size, StreamType uploadType)
m_uploadtype = BUFFERDATA;
else if(g_ogl_config.bSupportsGLSync && g_ActiveConfig.bHackedBufferUpload && (m_uploadtype & MAP_AND_RISK))
m_uploadtype = MAP_AND_RISK;
else if(g_ogl_config.bSupportsGLSync && g_ogl_config.bSupportsGLPinnedMemory && (!DriverDetails::HasBug(DriverDetails::BUG_BROKENPINNEDMEMORY) || type != GL_ELEMENT_ARRAY_BUFFER) && (m_uploadtype & PINNED_MEMORY))
else if(g_ogl_config.bSupportsGLSync && g_ogl_config.bSupportsGLPinnedMemory && !(DriverDetails::HasBug(DriverDetails::BUG_BROKENPINNEDMEMORY) && type == GL_ELEMENT_ARRAY_BUFFER) && (m_uploadtype & PINNED_MEMORY))
m_uploadtype = PINNED_MEMORY;
else if(nvidia && (m_uploadtype & BUFFERSUBDATA))
m_uploadtype = BUFFERSUBDATA;
@@ -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<SLOT(m_iterator); i++)
for(size_t i=SLOT(m_used_iterator); i<SLOT(m_iterator); i++)
{
fences[i] = glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
}
m_used_iterator = m_iterator;
// wait for new slots to end of buffer
for(u32 i=SLOT(m_free_iterator)+1; i<=SLOT(iter_end) && i < SYNC_POINTS; i++)
for (size_t i = SLOT(m_free_iterator) + 1; i <= SLOT(iter_end) && i < SYNC_POINTS; i++)
{
glClientWaitSync(fences[i], GL_SYNC_FLUSH_COMMANDS_BIT, GL_TIMEOUT_IGNORED);
glDeleteSync(fences[i]);
@@ -99,8 +99,10 @@ void StreamBuffer::Alloc ( size_t size, u32 stride )
if(iter_end >= 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<SLOT(m_iterator); i++)
}
for (size_t i = 0; i < SLOT(m_iterator); i++)
{
glDeleteSync(fences[i]);
}
delete [] fences;
}
@@ -59,15 +59,15 @@ struct VBOCache {
};
static std::map<u64,VBOCache> 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<u32> 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();
@@ -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);
}
@@ -28,8 +28,6 @@ using OGL::TextureCache;
static GLuint s_texConvFrameBuffer = 0;
static GLuint s_srcTexture = 0; // for decoding from RAM
static GLuint s_srcTextureWidth = 0;
static GLuint s_srcTextureHeight = 0;
static GLuint s_dstTexture = 0; // for encoding to RAM
const int renderBufferWidth = 1024;
@@ -44,11 +42,8 @@ static SHADER s_encodingPrograms[NUM_ENCODING_PROGRAMS];
static GLuint s_encode_VBO = 0;
static GLuint s_encode_VAO = 0;
static GLuint s_decode_VBO = 0;
static GLuint s_decode_VAO = 0;
static TargetRectangle s_cached_sourceRc;
static int s_cached_srcWidth = 0;
static int s_cached_srcHeight = 0;
static const char *VProgram =
"ATTRIN vec2 rawpos;\n"
@@ -62,6 +57,22 @@ static const char *VProgram =
void CreatePrograms()
{
/* TODO: Accuracy Improvements
*
* This shader doesn't really match what the gamecube does interally in the
* copy pipeline.
* 1. It uses Opengl's built in filtering when yscaling, someone could work
* out how the copypipeline does it's filtering and implement it correctly
* in this shader.
* 2. Deflickering isn't implemented, a futher filtering over 3 lines.
* Isn't really needed on non-interlaced monitors (and would lower quality;
* But hey, accuracy!)
* 3. Flipper's YUYV conversion implements a 3 pixel horozontal blur on the
* UV channels, centering the U channel on the Left pixel and the V channel
* on the Right pixel.
* The current implementation Centers both UV channels at the same place
* inbetween the two Pixels, and only blurs over these two pixels.
*/
// Output is BGRA because that is slightly faster than RGBA.
const char *FProgramRgbToYuyv =
"uniform sampler2DRect samp9;\n"
@@ -69,8 +80,8 @@ void CreatePrograms()
"COLOROUT(ocol0)\n"
"void main()\n"
"{\n"
" vec3 c0 = texture2DRect(samp9, uv0).rgb;\n"
" vec3 c1 = texture2DRect(samp9, uv0 + vec2(1.0, 0.0)).rgb;\n"
" vec3 c0 = texture2DRect(samp9, uv0 - dFdx(uv0) * 0.25).rgb;\n"
" vec3 c1 = texture2DRect(samp9, uv0 + dFdx(uv0) * 0.25).rgb;\n"
" vec3 c01 = (c0 + c1) * 0.5;\n"
" vec3 y_const = vec3(0.257,0.504,0.098);\n"
" vec3 u_const = vec3(-0.148,-0.291,0.439);\n"
@@ -79,15 +90,35 @@ void CreatePrograms()
" ocol0 = vec4(dot(c1,y_const),dot(c01,u_const),dot(c0,y_const),dot(c01, v_const)) + const3;\n"
"}\n";
/* TODO: Accuracy Improvements
*
* The YVYU to RGB conversion here matches the RGB to YUYV done above, but
* if a game modifies or adds images to the XFB then it should be using the
* same algorithm as the flipper, and could result in slight colour inaccuracies
* when run back through this shader.
*/
const char *VProgramYuyvToRgb =
"void main()\n"
"{\n"
" vec2 rawpos = vec2(gl_VertexID&1, gl_VertexID&2);\n"
" gl_Position = vec4(rawpos*2.0-1.0, 0.0, 1.0);\n"
"}\n";
const char *FProgramYuyvToRgb =
"uniform sampler2DRect samp9;\n"
"VARYIN vec2 uv0;\n"
"COLOROUT(ocol0)\n"
"void main()\n"
"{\n"
" vec4 c0 = texture2DRect(samp9, uv0).rgba;\n"
" float f = step(0.5, fract(uv0.x));\n"
" float y = mix(c0.b, c0.r, f);\n"
" ivec2 uv = ivec2(gl_FragCoord.xy);\n"
#ifdef USE_GLES3
// We switch top/bottom here. TODO: move this to screen blit.
" ivec2 ts = textureSize(samp9, 0);\n"
" vec4 c0 = texelFetch(samp9, ivec2(uv.x/2, ts.y-uv.y-1), 0);\n"
#else
" ivec2 ts = textureSize(samp9);\n"
" vec4 c0 = texelFetch(samp9, ivec2(uv.x/2, ts.y-uv.y-1));\n"
#endif
" float y = mix(c0.b, c0.r, uv.x & 1);\n"
" float yComp = 1.164 * (y - 0.0625);\n"
" float uComp = c0.g - 0.5;\n"
" float vComp = c0.a - 0.5;\n"
@@ -98,7 +129,7 @@ void CreatePrograms()
"}\n";
ProgramShaderCache::CompileShader(s_rgbToYuyvProgram, VProgram, FProgramRgbToYuyv);
ProgramShaderCache::CompileShader(s_yuyvToRgbProgram, VProgram, FProgramYuyvToRgb);
ProgramShaderCache::CompileShader(s_yuyvToRgbProgram, VProgramYuyvToRgb, FProgramYuyvToRgb);
}
SHADER &GetOrCreateEncodingShader(u32 format)
@@ -146,19 +177,8 @@ void Init()
s_cached_sourceRc.left = -1;
s_cached_sourceRc.right = -1;
glGenBuffers(1, &s_decode_VBO );
glGenVertexArrays(1, &s_decode_VAO );
glBindBuffer(GL_ARRAY_BUFFER, s_decode_VBO );
glBindVertexArray( s_decode_VAO );
s_cached_srcWidth = -1;
s_cached_srcHeight = -1;
glEnableVertexAttribArray(SHADER_POSITION_ATTRIB);
glVertexAttribPointer(SHADER_POSITION_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL);
glEnableVertexAttribArray(SHADER_TEXTURE0_ATTRIB);
glVertexAttribPointer(SHADER_TEXTURE0_ATTRIB, 2, GL_FLOAT, 0, sizeof(GLfloat)*4, (GLfloat*)NULL+2);
s_srcTextureWidth = 0;
s_srcTextureHeight = 0;
glActiveTexture(GL_TEXTURE0 + 9);
glGenTextures(1, &s_srcTexture);
@@ -180,7 +200,6 @@ void Shutdown()
glDeleteFramebuffers(1, &s_texConvFrameBuffer);
glDeleteBuffers(1, &s_encode_VBO );
glDeleteVertexArrays(1, &s_encode_VAO );
glDeleteBuffers(1, &s_decode_VBO );
glDeleteVertexArrays(1, &s_decode_VAO );
s_rgbToYuyvProgram.Destroy();
@@ -347,7 +366,10 @@ void EncodeToRamYUYV(GLuint srcTexture, const TargetRectangle& sourceRc, u8* des
s_rgbToYuyvProgram.Bind();
EncodeToRamUsingShader(srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, false);
// We enable linear filtering, because the gamecube does filtering in the vertical direction when
// yscale is enabled.
// Otherwise we get jaggies when a game uses yscaling (most PAL games)
EncodeToRamUsingShader(srcTexture, sourceRc, destAddr, dstWidth / 2, dstHeight, 0, false, true);
FramebufferManager::SetFramebuffer(0);
TextureCache::DisableStage(0);
g_renderer->RestoreAPIState();
@@ -365,8 +387,6 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTextur
return;
}
int srcFmtWidth = srcWidth / 2;
g_renderer->ResetAPIState(); // reset any game specific settings
// switch to texture converter frame buffer
@@ -380,50 +400,14 @@ void DecodeToTexture(u32 xfbAddr, int srcWidth, int srcHeight, GLuint destTextur
// set srcAddr as data for source texture
glActiveTexture(GL_TEXTURE0+9);
glBindTexture(getFbType(), s_srcTexture);
// TODO: make this less slow. (How?)
if ((GLsizei)s_srcTextureWidth == (GLsizei)srcFmtWidth && (GLsizei)s_srcTextureHeight == (GLsizei)srcHeight)
{
glTexSubImage2D(getFbType(), 0,0,0,s_srcTextureWidth, s_srcTextureHeight,
GL_BGRA, GL_UNSIGNED_BYTE, srcAddr);
}
else
{
glTexImage2D(getFbType(), 0, GL_RGBA, (GLsizei)srcFmtWidth, (GLsizei)srcHeight,
0, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr);
s_srcTextureWidth = (GLsizei)srcFmtWidth;
s_srcTextureHeight = (GLsizei)srcHeight;
}
glTexImage2D(getFbType(), 0, GL_RGBA, srcWidth / 2, srcHeight, 0, GL_BGRA, GL_UNSIGNED_BYTE, srcAddr);
glViewport(0, 0, srcWidth, srcHeight);
s_yuyvToRgbProgram.Bind();
GL_REPORT_ERRORD();
if(s_cached_srcHeight != srcHeight || s_cached_srcWidth != srcWidth) {
GLfloat vertices[] = {
1.f, -1.f,
(float)srcFmtWidth, (float)srcHeight,
1.f, 1.f,
(float)srcFmtWidth, 0.f,
-1.f, -1.f,
0.f, (float)srcHeight,
-1.f, 1.f,
0.f, 0.f
};
glBindBuffer(GL_ARRAY_BUFFER, s_decode_VBO );
glBufferData(GL_ARRAY_BUFFER, sizeof(GLfloat)*4*4, vertices, GL_STREAM_DRAW);
s_cached_srcHeight = srcHeight;
s_cached_srcWidth = srcWidth;
}
glBindVertexArray( s_decode_VAO );
glDrawArrays(GL_TRIANGLE_STRIP, 0, 4);
GL_REPORT_ERRORD();
FramebufferManager::SetFramebuffer(0);
g_renderer->RestoreAPIState();

Some files were not shown because too many files have changed in this diff Show More