mirror of
https://github.com/Retropex/dolphin.git
synced 2025-05-12 11:20:46 +02:00
Updated to 5.0-17430 for more optimisations!
This commit is contained in:
commit
aaa54ae2a7
@ -980,6 +980,10 @@ else()
|
||||
set(DOLPHIN_WC_IS_STABLE "0")
|
||||
endif()
|
||||
|
||||
# Remove in-tree revision information generated by Visual Studio
|
||||
# This is because the compiler will check in-tree first and use this, even if it is outdated
|
||||
file(REMOVE "${PROJECT_SOURCE_DIR}/Source/Core/Common/scmrev.h")
|
||||
|
||||
configure_file(
|
||||
"${PROJECT_SOURCE_DIR}/Source/Core/Common/scmrev.h.in"
|
||||
"${PROJECT_BINARY_DIR}/Source/Core/Common/scmrev.h"
|
||||
|
2
Externals/hidapi/CMakeLists.txt
vendored
2
Externals/hidapi/CMakeLists.txt
vendored
@ -9,7 +9,7 @@ if(APPLE)
|
||||
elseif(MSVC)
|
||||
target_sources(hidapi PRIVATE windows/hid.c)
|
||||
else()
|
||||
find_package(Libudev)
|
||||
find_package(LIBUDEV)
|
||||
if(CMAKE_SYSTEM_NAME STREQUAL "Linux" AND LIBUDEV_FOUND)
|
||||
target_sources(hidapi PRIVATE linux/hid.c)
|
||||
target_link_libraries(hidapi PRIVATE udev)
|
||||
|
@ -154,20 +154,6 @@ Section "Base" SEC01
|
||||
|
||||
SetOutPath "$TEMP"
|
||||
SetOverwrite on
|
||||
File /r "dxredist"
|
||||
File /r "vcredist"
|
||||
SectionEnd
|
||||
|
||||
Section "DirectX Runtime" SEC02
|
||||
DetailPrint "Running DirectX runtime setup..."
|
||||
ExecWait '"$TEMP\dxredist\DXSETUP.exe" /silent'
|
||||
DetailPrint "Finished DirectX runtime setup"
|
||||
SectionEnd
|
||||
|
||||
Section "Visual C++ 2015 Redistributable" SEC03
|
||||
DetailPrint "Running Visual C++ 2015 Redistributable setup..."
|
||||
ExecWait '"$TEMP\vcredist\vc_redist.x64.exe" /install /quiet /norestart'
|
||||
DetailPrint "Finished Visual C++ 2015 Redistributable setup"
|
||||
SectionEnd
|
||||
|
||||
Section -AdditionalIcons
|
||||
@ -193,8 +179,6 @@ SectionEnd
|
||||
; Section descriptions
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_BEGIN
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SEC01} "Installs all files required to run the Dolphin Emulator."
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SEC02} "Installs the recommended DirectX runtime libraries that are needed by Dolphin."
|
||||
!insertmacro MUI_DESCRIPTION_TEXT ${SEC03} "Installs the required Visual C++ 2015 Redistributable that is needed by Dolphin."
|
||||
!insertmacro MUI_FUNCTION_DESCRIPTION_END
|
||||
|
||||
Section Uninstall
|
||||
|
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
Binary file not shown.
@ -16,7 +16,7 @@ Primehack is now supported on MacOS thanks to the efforts of [Brandon Sorensen](
|
||||
|
||||
# Original Dolphin Readme file contents:
|
||||
|
||||
[Homepage](https://dolphin-emu.org/) | [Project Site](https://github.com/dolphin-emu/dolphin) | [Buildbot](https://dolphin.ci) | [Forums](https://forums.dolphin-emu.org) | [Wiki](https://wiki.dolphin-emu.org) | [Github Wiki](https://github.com/dolphin-emu/dolphin/wiki) | [Issue Tracker](https://bugs.dolphin-emu.org/projects/emulator/issues) | [Coding Style](https://github.com/dolphin-emu/dolphin/blob/master/Contributing.md) | [Transifex Page](https://www.transifex.com/projects/p/dolphin-emu)
|
||||
[Homepage](https://dolphin-emu.org/) | [Project Site](https://github.com/dolphin-emu/dolphin) | [Buildbot](https://dolphin.ci/) | [Forums](https://forums.dolphin-emu.org/) | [Wiki](https://wiki.dolphin-emu.org/) | [GitHub Wiki](https://github.com/dolphin-emu/dolphin/wiki) | [Issue Tracker](https://bugs.dolphin-emu.org/projects/emulator/issues) | [Coding Style](https://github.com/dolphin-emu/dolphin/blob/master/Contributing.md) | [Transifex Page](https://explore.transifex.com/delroth/dolphin-emu/)
|
||||
|
||||
Dolphin is an emulator for running GameCube and Wii games on Windows,
|
||||
Linux, macOS, and recent Android devices. It's licensed under the terms
|
||||
|
@ -14,9 +14,10 @@ import androidx.lifecycle.ViewModelProvider;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.divider.MaterialDividerItemDecoration;
|
||||
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.features.cheats.model.CheatsViewModel;
|
||||
import org.dolphinemu.dolphinemu.ui.DividerItemDecoration;
|
||||
|
||||
public class CheatListFragment extends Fragment
|
||||
{
|
||||
@ -38,6 +39,10 @@ public class CheatListFragment extends Fragment
|
||||
|
||||
recyclerView.setAdapter(new CheatsAdapter(activity, viewModel));
|
||||
recyclerView.setLayoutManager(new LinearLayoutManager(activity));
|
||||
recyclerView.addItemDecoration(new DividerItemDecoration(activity, null));
|
||||
|
||||
MaterialDividerItemDecoration divider =
|
||||
new MaterialDividerItemDecoration(requireActivity(), LinearLayoutManager.VERTICAL);
|
||||
divider.setLastItemDecorated(false);
|
||||
recyclerView.addItemDecoration(divider);
|
||||
}
|
||||
}
|
||||
|
@ -14,10 +14,11 @@ import androidx.fragment.app.Fragment;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
import com.google.android.material.divider.MaterialDividerItemDecoration;
|
||||
|
||||
import org.dolphinemu.dolphinemu.R;
|
||||
import org.dolphinemu.dolphinemu.features.settings.model.Settings;
|
||||
import org.dolphinemu.dolphinemu.features.settings.model.view.SettingsItem;
|
||||
import org.dolphinemu.dolphinemu.ui.DividerItemDecoration;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
@ -136,7 +137,11 @@ public final class SettingsFragment extends Fragment implements SettingsFragment
|
||||
|
||||
recyclerView.setAdapter(mAdapter);
|
||||
recyclerView.setLayoutManager(manager);
|
||||
recyclerView.addItemDecoration(new DividerItemDecoration(requireActivity(), null));
|
||||
|
||||
MaterialDividerItemDecoration divider =
|
||||
new MaterialDividerItemDecoration(requireActivity(), LinearLayoutManager.VERTICAL);
|
||||
divider.setLastItemDecorated(false);
|
||||
recyclerView.addItemDecoration(divider);
|
||||
|
||||
SettingsActivityView activity = (SettingsActivityView) getActivity();
|
||||
mPresenter.onViewCreated(menuTag, activity.getSettings());
|
||||
|
@ -1,162 +0,0 @@
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
package org.dolphinemu.dolphinemu.ui;
|
||||
|
||||
import android.content.Context;
|
||||
import android.content.res.TypedArray;
|
||||
import android.graphics.Canvas;
|
||||
import android.graphics.Rect;
|
||||
import android.graphics.drawable.Drawable;
|
||||
import android.util.AttributeSet;
|
||||
import android.view.View;
|
||||
|
||||
import androidx.annotation.NonNull;
|
||||
import androidx.recyclerview.widget.LinearLayoutManager;
|
||||
import androidx.recyclerview.widget.RecyclerView;
|
||||
|
||||
/**
|
||||
* Implementation from:
|
||||
* https://gist.github.com/lapastillaroja/858caf1a82791b6c1a36
|
||||
*/
|
||||
public final class DividerItemDecoration extends RecyclerView.ItemDecoration
|
||||
{
|
||||
|
||||
private Drawable mDivider;
|
||||
private boolean mShowFirstDivider = false;
|
||||
private boolean mShowLastDivider = false;
|
||||
|
||||
public DividerItemDecoration(Context context, AttributeSet attrs)
|
||||
{
|
||||
final TypedArray a = context
|
||||
.obtainStyledAttributes(attrs, new int[]{android.R.attr.listDivider});
|
||||
mDivider = a.getDrawable(0);
|
||||
a.recycle();
|
||||
}
|
||||
|
||||
public DividerItemDecoration(Context context, AttributeSet attrs, boolean showFirstDivider,
|
||||
boolean showLastDivider)
|
||||
{
|
||||
this(context, attrs);
|
||||
mShowFirstDivider = showFirstDivider;
|
||||
mShowLastDivider = showLastDivider;
|
||||
}
|
||||
|
||||
public DividerItemDecoration(Drawable divider)
|
||||
{
|
||||
mDivider = divider;
|
||||
}
|
||||
|
||||
public DividerItemDecoration(Drawable divider, boolean showFirstDivider,
|
||||
boolean showLastDivider)
|
||||
{
|
||||
this(divider);
|
||||
mShowFirstDivider = showFirstDivider;
|
||||
mShowLastDivider = showLastDivider;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void getItemOffsets(@NonNull Rect outRect, @NonNull View view,
|
||||
@NonNull RecyclerView parent,
|
||||
@NonNull RecyclerView.State state)
|
||||
{
|
||||
super.getItemOffsets(outRect, view, parent, state);
|
||||
if (mDivider == null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
if (parent.getChildAdapterPosition(view) < 1)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (getOrientation(parent) == LinearLayoutManager.VERTICAL)
|
||||
{
|
||||
outRect.top = mDivider.getIntrinsicHeight();
|
||||
}
|
||||
else
|
||||
{
|
||||
outRect.left = mDivider.getIntrinsicWidth();
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onDrawOver(@NonNull Canvas c, @NonNull RecyclerView parent,
|
||||
@NonNull RecyclerView.State state)
|
||||
{
|
||||
if (mDivider == null)
|
||||
{
|
||||
super.onDrawOver(c, parent, state);
|
||||
return;
|
||||
}
|
||||
|
||||
// Initialization needed to avoid compiler warning
|
||||
int left = 0, right = 0, top = 0, bottom = 0, size;
|
||||
int orientation = getOrientation(parent);
|
||||
int childCount = parent.getChildCount();
|
||||
|
||||
if (orientation == LinearLayoutManager.VERTICAL)
|
||||
{
|
||||
size = mDivider.getIntrinsicHeight();
|
||||
left = parent.getPaddingLeft();
|
||||
right = parent.getWidth() - parent.getPaddingRight();
|
||||
}
|
||||
else
|
||||
{ //horizontal
|
||||
size = mDivider.getIntrinsicWidth();
|
||||
top = parent.getPaddingTop();
|
||||
bottom = parent.getHeight() - parent.getPaddingBottom();
|
||||
}
|
||||
|
||||
for (int i = mShowFirstDivider ? 0 : 1; i < childCount; i++)
|
||||
{
|
||||
View child = parent.getChildAt(i);
|
||||
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
|
||||
|
||||
if (orientation == LinearLayoutManager.VERTICAL)
|
||||
{
|
||||
top = child.getTop() - params.topMargin;
|
||||
bottom = top + size;
|
||||
}
|
||||
else
|
||||
{ //horizontal
|
||||
left = child.getLeft() - params.leftMargin;
|
||||
right = left + size;
|
||||
}
|
||||
mDivider.setBounds(left, top, right, bottom);
|
||||
mDivider.draw(c);
|
||||
}
|
||||
|
||||
// show last divider
|
||||
if (mShowLastDivider && childCount > 0)
|
||||
{
|
||||
View child = parent.getChildAt(childCount - 1);
|
||||
RecyclerView.LayoutParams params = (RecyclerView.LayoutParams) child.getLayoutParams();
|
||||
if (orientation == LinearLayoutManager.VERTICAL)
|
||||
{
|
||||
top = child.getBottom() + params.bottomMargin;
|
||||
bottom = top + size;
|
||||
}
|
||||
else
|
||||
{ // horizontal
|
||||
left = child.getRight() + params.rightMargin;
|
||||
right = left + size;
|
||||
}
|
||||
mDivider.setBounds(left, top, right, bottom);
|
||||
mDivider.draw(c);
|
||||
}
|
||||
}
|
||||
|
||||
private int getOrientation(RecyclerView parent)
|
||||
{
|
||||
if (parent.getLayoutManager() instanceof LinearLayoutManager)
|
||||
{
|
||||
LinearLayoutManager layoutManager = (LinearLayoutManager) parent.getLayoutManager();
|
||||
return layoutManager.getOrientation();
|
||||
}
|
||||
else
|
||||
{
|
||||
throw new IllegalStateException(
|
||||
"DividerItemDecoration can only be used with a LinearLayoutManager.");
|
||||
}
|
||||
}
|
||||
}
|
@ -50,7 +50,7 @@
|
||||
app:layout_constraintWidth_max="400dp"
|
||||
app:layout_constraintEnd_toStartOf="@id/divider"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/divider"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
tools:text="@string/user_data_new_location" />
|
||||
|
||||
<TextView
|
||||
@ -84,15 +84,14 @@
|
||||
app:barrierDirection="end"
|
||||
app:constraint_referenced_ids="text_type,text_path,text_android_11" />
|
||||
|
||||
<View
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="#1F000000"
|
||||
android:layout_marginStart="24dp"
|
||||
android:layout_marginEnd="24dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
app:layout_constraintTop_toTopOf="@id/text_type"
|
||||
app:layout_constraintBottom_toBottomOf="@id/text_android_11"
|
||||
app:layout_constraintStart_toEndOf="@id/barrier_text"
|
||||
app:layout_constraintEnd_toStartOf="@id/barrier_buttons" />
|
||||
|
||||
|
@ -53,11 +53,10 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toStartOf="@id/divider" />
|
||||
|
||||
<View
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="1dp"
|
||||
android:layout_height="0dp"
|
||||
android:background="#1F000000"
|
||||
android:layout_marginStart="24dp"
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toBottomOf="parent"
|
||||
|
@ -51,11 +51,10 @@
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/divider" />
|
||||
|
||||
<View
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:background="#1F000000"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
@ -52,11 +52,10 @@
|
||||
app:layout_constraintTop_toTopOf="parent"
|
||||
app:layout_constraintBottom_toTopOf="@id/divider" />
|
||||
|
||||
<View
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:id="@+id/divider"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:background="#1F000000"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginHorizontal="@dimen/spacing_large"
|
||||
android:layout_marginVertical="@dimen/spacing_small"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
|
@ -44,11 +44,10 @@
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintTop_toBottomOf="@id/text_description" />
|
||||
|
||||
<View
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:id="@+id/divider_1"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:background="#1F000000"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
@ -145,11 +144,10 @@
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
app:layout_constraintBaseline_toBaselineOf="@id/label_revision" />
|
||||
|
||||
<View
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:id="@+id/divider_2"
|
||||
android:layout_width="0dp"
|
||||
android:layout_height="1dp"
|
||||
android:background="#1F000000"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="32dp"
|
||||
app:layout_constraintStart_toStartOf="parent"
|
||||
app:layout_constraintEnd_toEndOf="parent"
|
||||
|
@ -110,13 +110,12 @@
|
||||
|
||||
</ScrollView>
|
||||
|
||||
<View
|
||||
android:id="@+id/divider"
|
||||
<com.google.android.material.divider.MaterialDivider
|
||||
android:id="@+id/divider_2"
|
||||
android:layout_width="match_parent"
|
||||
android:layout_height="1dp"
|
||||
android:background="?attr/colorOnSurfaceVariant"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_marginTop="24dp"
|
||||
android:layout_marginBottom="16dp"/>
|
||||
android:layout_marginBottom="16dp" />
|
||||
|
||||
<Button
|
||||
android:id="@+id/menu_exit"
|
||||
|
@ -58,4 +58,8 @@
|
||||
<item name="tickVisible">false</item>
|
||||
<item name="labelBehavior">gone</item>
|
||||
</style>
|
||||
|
||||
<style name="DolphinDivider" parent="Widget.Material3.MaterialDivider">
|
||||
<item name="dividerColor">?attr/colorSurfaceVariant</item>
|
||||
</style>
|
||||
</resources>
|
||||
|
@ -54,6 +54,7 @@
|
||||
<item name="materialAlertDialogTheme">@style/DolphinMaterialDialog</item>
|
||||
<item name="popupTheme">@style/DolphinPopup</item>
|
||||
<item name="sliderStyle">@style/DolphinSlider</item>
|
||||
<item name="materialDividerStyle">@style/DolphinDivider</item>
|
||||
</style>
|
||||
|
||||
<!-- Trick for API >= 27 specific changes -->
|
||||
|
@ -485,13 +485,22 @@ void ARM64XEmitter::EncodeLoadStorePairedInst(u32 op, ARM64Reg Rt, ARM64Reg Rt2,
|
||||
bool bVec = IsVector(Rt);
|
||||
|
||||
if (b128Bit)
|
||||
{
|
||||
ASSERT_MSG(DYNA_REC, (imm & 0xf) == 0, "128-bit load/store must use aligned offset: {}", imm);
|
||||
imm >>= 4;
|
||||
}
|
||||
else if (b64Bit)
|
||||
{
|
||||
ASSERT_MSG(DYNA_REC, (imm & 0x7) == 0, "64-bit load/store must use aligned offset: {}", imm);
|
||||
imm >>= 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_MSG(DYNA_REC, (imm & 0x3) == 0, "32-bit load/store must use aligned offset: {}", imm);
|
||||
imm >>= 2;
|
||||
}
|
||||
|
||||
ASSERT_MSG(DYNA_REC, !(imm & ~0xF), "offset too large {}", imm);
|
||||
ASSERT_MSG(DYNA_REC, (imm & ~0xF) == 0, "offset too large {}", imm);
|
||||
|
||||
u32 opc = 0;
|
||||
if (b128Bit)
|
||||
@ -524,11 +533,20 @@ void ARM64XEmitter::EncodeLoadStoreIndexedInst(u32 op, ARM64Reg Rt, ARM64Reg Rn,
|
||||
bool bVec = IsVector(Rt);
|
||||
|
||||
if (size == 64)
|
||||
{
|
||||
ASSERT_MSG(DYNA_REC, (imm & 0x7) == 0, "64-bit load/store must use aligned offset: {}", imm);
|
||||
imm >>= 3;
|
||||
}
|
||||
else if (size == 32)
|
||||
{
|
||||
ASSERT_MSG(DYNA_REC, (imm & 0x3) == 0, "32-bit load/store must use aligned offset: {}", imm);
|
||||
imm >>= 2;
|
||||
}
|
||||
else if (size == 16)
|
||||
{
|
||||
ASSERT_MSG(DYNA_REC, (imm & 0x1) == 0, "16-bit load/store must use aligned offset: {}", imm);
|
||||
imm >>= 1;
|
||||
}
|
||||
|
||||
ASSERT_MSG(DYNA_REC, imm >= 0, "(IndexType::Unsigned): offset must be positive {}", imm);
|
||||
ASSERT_MSG(DYNA_REC, !(imm & ~0xFFF), "(IndexType::Unsigned): offset too large {}", imm);
|
||||
@ -615,10 +633,12 @@ void ARM64XEmitter::EncodeLoadStorePair(u32 op, u32 load, IndexType type, ARM64R
|
||||
if (b64Bit)
|
||||
{
|
||||
op |= 0b10;
|
||||
ASSERT_MSG(DYNA_REC, (imm & 0x7) == 0, "64-bit load/store must use aligned offset: {}", imm);
|
||||
imm >>= 3;
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT_MSG(DYNA_REC, (imm & 0x3) == 0, "32-bit load/store must use aligned offset: {}", imm);
|
||||
imm >>= 2;
|
||||
}
|
||||
|
||||
@ -2072,19 +2092,29 @@ void ARM64FloatEmitter::EmitLoadStoreImmediate(u8 size, u32 opc, IndexType type,
|
||||
|
||||
if (type == IndexType::Unsigned)
|
||||
{
|
||||
ASSERT_MSG(DYNA_REC, !(imm & ((size - 1) >> 3)),
|
||||
"(IndexType::Unsigned) immediate offset must be aligned to size! ({}) ({})", imm,
|
||||
fmt::ptr(m_emit->GetCodePtr()));
|
||||
ASSERT_MSG(DYNA_REC, imm >= 0, "(IndexType::Unsigned) immediate offset must be positive! ({})",
|
||||
imm);
|
||||
if (size == 16)
|
||||
{
|
||||
ASSERT_MSG(DYNA_REC, (imm & 0x1) == 0, "16-bit load/store must use aligned offset: {}", imm);
|
||||
imm >>= 1;
|
||||
}
|
||||
else if (size == 32)
|
||||
{
|
||||
ASSERT_MSG(DYNA_REC, (imm & 0x3) == 0, "32-bit load/store must use aligned offset: {}", imm);
|
||||
imm >>= 2;
|
||||
}
|
||||
else if (size == 64)
|
||||
{
|
||||
ASSERT_MSG(DYNA_REC, (imm & 0x7) == 0, "64-bit load/store must use aligned offset: {}", imm);
|
||||
imm >>= 3;
|
||||
}
|
||||
else if (size == 128)
|
||||
{
|
||||
ASSERT_MSG(DYNA_REC, (imm & 0xf) == 0, "128-bit load/store must use aligned offset: {}", imm);
|
||||
imm >>= 4;
|
||||
}
|
||||
ASSERT_MSG(DYNA_REC, imm <= 0xFFF, "Immediate value is too big: {}", imm);
|
||||
encoded_imm = (imm & 0xFFF);
|
||||
}
|
||||
else
|
||||
|
@ -24,6 +24,11 @@ union TVec3
|
||||
{
|
||||
}
|
||||
|
||||
constexpr bool operator==(const TVec3& other) const
|
||||
{
|
||||
return x == other.x && y == other.y && z == other.z;
|
||||
}
|
||||
|
||||
constexpr TVec3 Cross(const TVec3& rhs) const
|
||||
{
|
||||
return {(y * rhs.z) - (rhs.y * z), (z * rhs.x) - (rhs.z * x), (x * rhs.y) - (rhs.x * y)};
|
||||
@ -153,6 +158,11 @@ union TVec4
|
||||
constexpr TVec4(TVec3<T> _vec, T _w) : TVec4{_vec.x, _vec.y, _vec.z, _w} {}
|
||||
constexpr TVec4(T _x, T _y, T _z, T _w) : data{_x, _y, _z, _w} {}
|
||||
|
||||
constexpr bool operator==(const TVec4& other) const
|
||||
{
|
||||
return x == other.x && y == other.y && z == other.z && w == other.w;
|
||||
}
|
||||
|
||||
constexpr T Dot(const TVec4& other) const
|
||||
{
|
||||
return x * other.x + y * other.y + z * other.z + w * other.w;
|
||||
@ -216,6 +226,8 @@ union TVec2
|
||||
{
|
||||
}
|
||||
|
||||
constexpr bool operator==(const TVec2& other) const { return x == other.x && y == other.y; }
|
||||
|
||||
constexpr T Cross(const TVec2& rhs) const { return (x * rhs.y) - (y * rhs.x); }
|
||||
constexpr T Dot(const TVec2& rhs) const { return (x * rhs.x) + (y * rhs.y); }
|
||||
constexpr T LengthSquared() const { return Dot(*this); }
|
||||
|
@ -29,7 +29,7 @@ using StringTranslator = std::string (*)(const char* text);
|
||||
void RegisterMsgAlertHandler(MsgAlertHandler handler);
|
||||
void RegisterStringTranslator(StringTranslator translator);
|
||||
|
||||
std::string GetStringT(const char* string);
|
||||
[[nodiscard]] std::string GetStringT(const char* string);
|
||||
|
||||
bool MsgAlertFmtImpl(bool yes_no, MsgType style, Common::Log::LogType log_type, const char* file,
|
||||
int line, fmt::string_view format, const fmt::format_args& args);
|
||||
|
@ -91,11 +91,7 @@ bool BootCore(std::unique_ptr<BootParameters> boot, const WindowSystemInfo& wsi)
|
||||
return false;
|
||||
|
||||
Config::AddLayer(ConfigLoaders::GenerateNetPlayConfigLoader(*netplay_settings));
|
||||
StartUp.bCopyWiiSaveNetplay = netplay_settings->m_CopyWiiSave;
|
||||
}
|
||||
else
|
||||
{
|
||||
g_SRAM_netplay_initialized = false;
|
||||
StartUp.bCopyWiiSaveNetplay = netplay_settings->copy_wii_save;
|
||||
}
|
||||
|
||||
// Override out-of-region languages/countries to prevent games from crashing or behaving oddly
|
||||
|
@ -30,99 +30,99 @@ public:
|
||||
|
||||
void Load(Config::Layer* layer) override
|
||||
{
|
||||
layer->Set(Config::MAIN_CPU_THREAD, m_settings.m_CPUthread);
|
||||
layer->Set(Config::MAIN_CPU_CORE, m_settings.m_CPUcore);
|
||||
layer->Set(Config::MAIN_ENABLE_CHEATS, m_settings.m_EnableCheats);
|
||||
layer->Set(Config::MAIN_GC_LANGUAGE, m_settings.m_SelectedLanguage);
|
||||
layer->Set(Config::MAIN_OVERRIDE_REGION_SETTINGS, m_settings.m_OverrideRegionSettings);
|
||||
layer->Set(Config::MAIN_DSP_HLE, m_settings.m_DSPHLE);
|
||||
layer->Set(Config::MAIN_OVERCLOCK_ENABLE, m_settings.m_OCEnable);
|
||||
layer->Set(Config::MAIN_OVERCLOCK, m_settings.m_OCFactor);
|
||||
layer->Set(Config::MAIN_CPU_THREAD, m_settings.cpu_thread);
|
||||
layer->Set(Config::MAIN_CPU_CORE, m_settings.cpu_core);
|
||||
layer->Set(Config::MAIN_ENABLE_CHEATS, m_settings.enable_cheats);
|
||||
layer->Set(Config::MAIN_GC_LANGUAGE, m_settings.selected_language);
|
||||
layer->Set(Config::MAIN_OVERRIDE_REGION_SETTINGS, m_settings.override_region_settings);
|
||||
layer->Set(Config::MAIN_DSP_HLE, m_settings.dsp_hle);
|
||||
layer->Set(Config::MAIN_OVERCLOCK_ENABLE, m_settings.oc_enable);
|
||||
layer->Set(Config::MAIN_OVERCLOCK, m_settings.oc_factor);
|
||||
for (ExpansionInterface::Slot slot : ExpansionInterface::SLOTS)
|
||||
layer->Set(Config::GetInfoForEXIDevice(slot), m_settings.m_EXIDevice[slot]);
|
||||
layer->Set(Config::MAIN_MEMORY_CARD_SIZE, m_settings.m_MemcardSizeOverride);
|
||||
layer->Set(Config::SESSION_SAVE_DATA_WRITABLE, m_settings.m_WriteToMemcard);
|
||||
layer->Set(Config::MAIN_RAM_OVERRIDE_ENABLE, m_settings.m_RAMOverrideEnable);
|
||||
layer->Set(Config::MAIN_MEM1_SIZE, m_settings.m_Mem1Size);
|
||||
layer->Set(Config::MAIN_MEM2_SIZE, m_settings.m_Mem2Size);
|
||||
layer->Set(Config::MAIN_FALLBACK_REGION, m_settings.m_FallbackRegion);
|
||||
layer->Set(Config::MAIN_ALLOW_SD_WRITES, m_settings.m_AllowSDWrites);
|
||||
layer->Set(Config::MAIN_DSP_JIT, m_settings.m_DSPEnableJIT);
|
||||
layer->Set(Config::GetInfoForEXIDevice(slot), m_settings.exi_device[slot]);
|
||||
layer->Set(Config::MAIN_MEMORY_CARD_SIZE, m_settings.memcard_size_override);
|
||||
layer->Set(Config::SESSION_SAVE_DATA_WRITABLE, m_settings.write_to_memcard);
|
||||
layer->Set(Config::MAIN_RAM_OVERRIDE_ENABLE, m_settings.ram_override_enable);
|
||||
layer->Set(Config::MAIN_MEM1_SIZE, m_settings.mem1_size);
|
||||
layer->Set(Config::MAIN_MEM2_SIZE, m_settings.mem2_size);
|
||||
layer->Set(Config::MAIN_FALLBACK_REGION, m_settings.fallback_region);
|
||||
layer->Set(Config::MAIN_ALLOW_SD_WRITES, m_settings.allow_sd_writes);
|
||||
layer->Set(Config::MAIN_DSP_JIT, m_settings.dsp_enable_jit);
|
||||
|
||||
for (size_t i = 0; i < Config::SYSCONF_SETTINGS.size(); ++i)
|
||||
{
|
||||
std::visit(
|
||||
[&](auto* info) {
|
||||
layer->Set(*info, static_cast<decltype(info->GetDefaultValue())>(
|
||||
m_settings.m_SYSCONFSettings[i]));
|
||||
m_settings.sysconf_settings[i]));
|
||||
},
|
||||
Config::SYSCONF_SETTINGS[i].config_info);
|
||||
}
|
||||
|
||||
layer->Set(Config::GFX_HACK_EFB_ACCESS_ENABLE, m_settings.m_EFBAccessEnable);
|
||||
layer->Set(Config::GFX_HACK_BBOX_ENABLE, m_settings.m_BBoxEnable);
|
||||
layer->Set(Config::GFX_HACK_FORCE_PROGRESSIVE, m_settings.m_ForceProgressive);
|
||||
layer->Set(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM, m_settings.m_EFBToTextureEnable);
|
||||
layer->Set(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM, m_settings.m_XFBToTextureEnable);
|
||||
layer->Set(Config::GFX_HACK_DISABLE_COPY_TO_VRAM, m_settings.m_DisableCopyToVRAM);
|
||||
layer->Set(Config::GFX_HACK_IMMEDIATE_XFB, m_settings.m_ImmediateXFBEnable);
|
||||
layer->Set(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES, m_settings.m_EFBEmulateFormatChanges);
|
||||
layer->Set(Config::GFX_HACK_EFB_ACCESS_ENABLE, m_settings.efb_access_enable);
|
||||
layer->Set(Config::GFX_HACK_BBOX_ENABLE, m_settings.bbox_enable);
|
||||
layer->Set(Config::GFX_HACK_FORCE_PROGRESSIVE, m_settings.force_progressive);
|
||||
layer->Set(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM, m_settings.efb_to_texture_enable);
|
||||
layer->Set(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM, m_settings.xfb_to_texture_enable);
|
||||
layer->Set(Config::GFX_HACK_DISABLE_COPY_TO_VRAM, m_settings.disable_copy_to_vram);
|
||||
layer->Set(Config::GFX_HACK_IMMEDIATE_XFB, m_settings.immediate_xfb_enable);
|
||||
layer->Set(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES, m_settings.efb_emulate_format_changes);
|
||||
layer->Set(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES,
|
||||
m_settings.m_SafeTextureCacheColorSamples);
|
||||
layer->Set(Config::GFX_PERF_QUERIES_ENABLE, m_settings.m_PerfQueriesEnable);
|
||||
layer->Set(Config::MAIN_FLOAT_EXCEPTIONS, m_settings.m_FloatExceptions);
|
||||
layer->Set(Config::MAIN_DIVIDE_BY_ZERO_EXCEPTIONS, m_settings.m_DivideByZeroExceptions);
|
||||
layer->Set(Config::MAIN_FPRF, m_settings.m_FPRF);
|
||||
layer->Set(Config::MAIN_ACCURATE_NANS, m_settings.m_AccurateNaNs);
|
||||
layer->Set(Config::MAIN_DISABLE_ICACHE, m_settings.m_DisableICache);
|
||||
layer->Set(Config::MAIN_SYNC_ON_SKIP_IDLE, m_settings.m_SyncOnSkipIdle);
|
||||
layer->Set(Config::MAIN_SYNC_GPU, m_settings.m_SyncGPU);
|
||||
layer->Set(Config::MAIN_SYNC_GPU_MAX_DISTANCE, m_settings.m_SyncGpuMaxDistance);
|
||||
layer->Set(Config::MAIN_SYNC_GPU_MIN_DISTANCE, m_settings.m_SyncGpuMinDistance);
|
||||
layer->Set(Config::MAIN_SYNC_GPU_OVERCLOCK, m_settings.m_SyncGpuOverclock);
|
||||
m_settings.safe_texture_cache_color_samples);
|
||||
layer->Set(Config::GFX_PERF_QUERIES_ENABLE, m_settings.perf_queries_enable);
|
||||
layer->Set(Config::MAIN_FLOAT_EXCEPTIONS, m_settings.float_exceptions);
|
||||
layer->Set(Config::MAIN_DIVIDE_BY_ZERO_EXCEPTIONS, m_settings.divide_by_zero_exceptions);
|
||||
layer->Set(Config::MAIN_FPRF, m_settings.fprf);
|
||||
layer->Set(Config::MAIN_ACCURATE_NANS, m_settings.accurate_nans);
|
||||
layer->Set(Config::MAIN_DISABLE_ICACHE, m_settings.disable_icache);
|
||||
layer->Set(Config::MAIN_SYNC_ON_SKIP_IDLE, m_settings.sync_on_skip_idle);
|
||||
layer->Set(Config::MAIN_SYNC_GPU, m_settings.sync_gpu);
|
||||
layer->Set(Config::MAIN_SYNC_GPU_MAX_DISTANCE, m_settings.sync_gpu_max_distance);
|
||||
layer->Set(Config::MAIN_SYNC_GPU_MIN_DISTANCE, m_settings.sync_gpu_min_distance);
|
||||
layer->Set(Config::MAIN_SYNC_GPU_OVERCLOCK, m_settings.sync_gpu_overclock);
|
||||
|
||||
layer->Set(Config::MAIN_JIT_FOLLOW_BRANCH, m_settings.m_JITFollowBranch);
|
||||
layer->Set(Config::MAIN_FAST_DISC_SPEED, m_settings.m_FastDiscSpeed);
|
||||
layer->Set(Config::MAIN_MMU, m_settings.m_MMU);
|
||||
layer->Set(Config::MAIN_FASTMEM, m_settings.m_Fastmem);
|
||||
layer->Set(Config::MAIN_SKIP_IPL, m_settings.m_SkipIPL);
|
||||
layer->Set(Config::SESSION_LOAD_IPL_DUMP, m_settings.m_LoadIPLDump);
|
||||
layer->Set(Config::MAIN_JIT_FOLLOW_BRANCH, m_settings.jit_follow_branch);
|
||||
layer->Set(Config::MAIN_FAST_DISC_SPEED, m_settings.fast_disc_speed);
|
||||
layer->Set(Config::MAIN_MMU, m_settings.mmu);
|
||||
layer->Set(Config::MAIN_FASTMEM, m_settings.fastmem);
|
||||
layer->Set(Config::MAIN_SKIP_IPL, m_settings.skip_ipl);
|
||||
layer->Set(Config::SESSION_LOAD_IPL_DUMP, m_settings.load_ipl_dump);
|
||||
|
||||
layer->Set(Config::GFX_HACK_DEFER_EFB_COPIES, m_settings.m_DeferEFBCopies);
|
||||
layer->Set(Config::GFX_HACK_EFB_ACCESS_TILE_SIZE, m_settings.m_EFBAccessTileSize);
|
||||
layer->Set(Config::GFX_HACK_EFB_DEFER_INVALIDATION, m_settings.m_EFBAccessDeferInvalidation);
|
||||
layer->Set(Config::GFX_HACK_DEFER_EFB_COPIES, m_settings.defer_efb_copies);
|
||||
layer->Set(Config::GFX_HACK_EFB_ACCESS_TILE_SIZE, m_settings.efb_access_tile_size);
|
||||
layer->Set(Config::GFX_HACK_EFB_DEFER_INVALIDATION, m_settings.efb_access_defer_invalidation);
|
||||
|
||||
layer->Set(Config::SESSION_USE_FMA, m_settings.m_UseFMA);
|
||||
layer->Set(Config::SESSION_USE_FMA, m_settings.use_fma);
|
||||
|
||||
layer->Set(Config::MAIN_BLUETOOTH_PASSTHROUGH_ENABLED, false);
|
||||
|
||||
if (m_settings.m_StrictSettingsSync)
|
||||
if (m_settings.strict_settings_sync)
|
||||
{
|
||||
layer->Set(Config::GFX_HACK_VERTEX_ROUNDING, m_settings.m_VertexRounding);
|
||||
layer->Set(Config::GFX_EFB_SCALE, m_settings.m_InternalResolution);
|
||||
layer->Set(Config::GFX_HACK_COPY_EFB_SCALED, m_settings.m_EFBScaledCopy);
|
||||
layer->Set(Config::GFX_FAST_DEPTH_CALC, m_settings.m_FastDepthCalc);
|
||||
layer->Set(Config::GFX_ENABLE_PIXEL_LIGHTING, m_settings.m_EnablePixelLighting);
|
||||
layer->Set(Config::GFX_WIDESCREEN_HACK, m_settings.m_WidescreenHack);
|
||||
layer->Set(Config::GFX_ENHANCE_FORCE_FILTERING, m_settings.m_ForceFiltering);
|
||||
layer->Set(Config::GFX_ENHANCE_MAX_ANISOTROPY, m_settings.m_MaxAnisotropy);
|
||||
layer->Set(Config::GFX_ENHANCE_FORCE_TRUE_COLOR, m_settings.m_ForceTrueColor);
|
||||
layer->Set(Config::GFX_ENHANCE_DISABLE_COPY_FILTER, m_settings.m_DisableCopyFilter);
|
||||
layer->Set(Config::GFX_DISABLE_FOG, m_settings.m_DisableFog);
|
||||
layer->Set(Config::GFX_HACK_VERTEX_ROUNDING, m_settings.vertex_rounding);
|
||||
layer->Set(Config::GFX_EFB_SCALE, m_settings.internal_resolution);
|
||||
layer->Set(Config::GFX_HACK_COPY_EFB_SCALED, m_settings.efb_scaled_copy);
|
||||
layer->Set(Config::GFX_FAST_DEPTH_CALC, m_settings.fast_depth_calc);
|
||||
layer->Set(Config::GFX_ENABLE_PIXEL_LIGHTING, m_settings.enable_pixel_lighting);
|
||||
layer->Set(Config::GFX_WIDESCREEN_HACK, m_settings.widescreen_hack);
|
||||
layer->Set(Config::GFX_ENHANCE_FORCE_FILTERING, m_settings.force_filtering);
|
||||
layer->Set(Config::GFX_ENHANCE_MAX_ANISOTROPY, m_settings.max_anisotropy);
|
||||
layer->Set(Config::GFX_ENHANCE_FORCE_TRUE_COLOR, m_settings.force_true_color);
|
||||
layer->Set(Config::GFX_ENHANCE_DISABLE_COPY_FILTER, m_settings.disable_copy_filter);
|
||||
layer->Set(Config::GFX_DISABLE_FOG, m_settings.disable_fog);
|
||||
layer->Set(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION,
|
||||
m_settings.m_ArbitraryMipmapDetection);
|
||||
m_settings.arbitrary_mipmap_detection);
|
||||
layer->Set(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION_THRESHOLD,
|
||||
m_settings.m_ArbitraryMipmapDetectionThreshold);
|
||||
layer->Set(Config::GFX_ENABLE_GPU_TEXTURE_DECODING, m_settings.m_EnableGPUTextureDecoding);
|
||||
m_settings.arbitrary_mipmap_detection_threshold);
|
||||
layer->Set(Config::GFX_ENABLE_GPU_TEXTURE_DECODING, m_settings.enable_gpu_texture_decoding);
|
||||
|
||||
// Disable AA as it isn't deterministic across GPUs
|
||||
layer->Set(Config::GFX_MSAA, 1);
|
||||
layer->Set(Config::GFX_SSAA, false);
|
||||
}
|
||||
|
||||
if (m_settings.m_SyncSaveData)
|
||||
if (m_settings.sync_save_data)
|
||||
{
|
||||
if (!m_settings.m_IsHosting)
|
||||
if (!m_settings.is_hosting)
|
||||
{
|
||||
const std::string path = File::GetUserPath(D_GCUSER_IDX) + GC_MEMCARD_NETPLAY DIR_SEP;
|
||||
layer->Set(Config::MAIN_GCI_FOLDER_A_PATH_OVERRIDE, path + "Card A");
|
||||
@ -130,7 +130,7 @@ public:
|
||||
|
||||
const auto make_memcard_path = [this](char letter) {
|
||||
return fmt::format("{}{}{}.{}.raw", File::GetUserPath(D_GCUSER_IDX), GC_MEMCARD_NETPLAY,
|
||||
letter, m_settings.m_SaveDataRegion);
|
||||
letter, m_settings.save_data_region);
|
||||
};
|
||||
layer->Set(Config::MAIN_MEMCARD_A_PATH, make_memcard_path('A'));
|
||||
layer->Set(Config::MAIN_MEMCARD_B_PATH, make_memcard_path('B'));
|
||||
@ -140,14 +140,14 @@ public:
|
||||
}
|
||||
|
||||
#ifdef HAS_LIBMGBA
|
||||
for (size_t i = 0; i < m_settings.m_GBARomPaths.size(); ++i)
|
||||
for (size_t i = 0; i < m_settings.gba_rom_paths.size(); ++i)
|
||||
{
|
||||
layer->Set(Config::MAIN_GBA_ROM_PATHS[i], m_settings.m_GBARomPaths[i]);
|
||||
layer->Set(Config::MAIN_GBA_ROM_PATHS[i], m_settings.gba_rom_paths[i]);
|
||||
}
|
||||
#endif
|
||||
|
||||
// Check To Override Client's Cheat Codes
|
||||
if (m_settings.m_SyncCodes && !m_settings.m_IsHosting)
|
||||
if (m_settings.sync_codes && !m_settings.is_hosting)
|
||||
{
|
||||
// Raise flag to use host's codes
|
||||
layer->Set(Config::SESSION_CODE_SYNC_OVERRIDE, true);
|
||||
|
@ -511,7 +511,7 @@ static void EmuThread(std::unique_ptr<BootParameters> boot, WindowSystemInfo wsi
|
||||
AudioCommon::InitSoundStream();
|
||||
Common::ScopeGuard audio_guard{&AudioCommon::ShutdownSoundStream};
|
||||
|
||||
HW::Init();
|
||||
HW::Init(NetPlay::IsNetPlayRunning() ? &(boot_session_data.GetNetplaySettings()->sram) : nullptr);
|
||||
|
||||
Common::ScopeGuard hw_guard{[] {
|
||||
// We must set up this flag before executing HW::Shutdown()
|
||||
|
@ -55,6 +55,11 @@ public:
|
||||
|
||||
OPCODE_CALLBACK(CPState& GetCPState()) { return m_cpmem; }
|
||||
|
||||
OPCODE_CALLBACK(u32 GetVertexSize(u8 vat))
|
||||
{
|
||||
return VertexLoaderBase::GetVertexSize(GetCPState().vtx_desc, GetCPState().vtx_attr[vat]);
|
||||
}
|
||||
|
||||
bool m_start_of_primitives = false;
|
||||
bool m_end_of_primitives = false;
|
||||
bool m_efb_copy = false;
|
||||
|
@ -45,6 +45,11 @@ public:
|
||||
|
||||
OPCODE_CALLBACK(CPState& GetCPState()) { return m_cpmem; }
|
||||
|
||||
OPCODE_CALLBACK(u32 GetVertexSize(u8 vat))
|
||||
{
|
||||
return VertexLoaderBase::GetVertexSize(GetCPState().vtx_desc, GetCPState().vtx_attr[vat]);
|
||||
}
|
||||
|
||||
private:
|
||||
void ProcessVertexComponent(CPArray array_index, VertexComponentFormat array_type,
|
||||
u32 component_offset, u32 vertex_size, u16 num_vertices,
|
||||
|
@ -8,6 +8,7 @@
|
||||
|
||||
#include "Common/ChunkFile.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/IOFile.h"
|
||||
|
||||
#include "Core/Config/MainSettings.h"
|
||||
#include "Core/ConfigManager.h"
|
||||
@ -20,11 +21,11 @@
|
||||
#include "Core/HW/Sram.h"
|
||||
#include "Core/HW/SystemTimers.h"
|
||||
#include "Core/Movie.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
#include "DiscIO/Enums.h"
|
||||
|
||||
Sram g_SRAM;
|
||||
bool g_SRAM_netplay_initialized = false;
|
||||
bool s_using_overridden_sram = false;
|
||||
|
||||
namespace ExpansionInterface
|
||||
{
|
||||
@ -102,11 +103,18 @@ u8 SlotToEXIDevice(Slot slot)
|
||||
}
|
||||
}
|
||||
|
||||
void Init()
|
||||
void Init(const Sram* override_sram)
|
||||
{
|
||||
if (!g_SRAM_netplay_initialized)
|
||||
auto& sram = Core::System::GetInstance().GetSRAM();
|
||||
if (override_sram)
|
||||
{
|
||||
InitSRAM();
|
||||
sram = *override_sram;
|
||||
s_using_overridden_sram = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
InitSRAM(&sram, SConfig::GetInstance().m_strSRAM);
|
||||
s_using_overridden_sram = false;
|
||||
}
|
||||
|
||||
CEXIMemoryCard::Init();
|
||||
@ -118,9 +126,9 @@ void Init()
|
||||
size_mbits = Memcard::MBIT_SIZE_MEMORY_CARD_59 << size_override;
|
||||
const bool shift_jis =
|
||||
Config::ToGameCubeRegion(SConfig::GetInstance().m_region) == DiscIO::Region::NTSC_J;
|
||||
const CardFlashId& flash_id = g_SRAM.settings_ex.flash_id[Memcard::SLOT_A];
|
||||
const u32 rtc_bias = g_SRAM.settings.rtc_bias;
|
||||
const u32 sram_language = static_cast<u32>(g_SRAM.settings.language);
|
||||
const CardFlashId& flash_id = sram.settings_ex.flash_id[Memcard::SLOT_A];
|
||||
const u32 rtc_bias = sram.settings.rtc_bias;
|
||||
const u32 sram_language = static_cast<u32>(sram.settings.language);
|
||||
const u64 format_time =
|
||||
Common::Timer::GetLocalTimeSinceJan1970() - ExpansionInterface::CEXIIPL::GC_EPOCH;
|
||||
|
||||
@ -151,6 +159,13 @@ void Shutdown()
|
||||
channel.reset();
|
||||
|
||||
CEXIMemoryCard::Shutdown();
|
||||
|
||||
if (!s_using_overridden_sram)
|
||||
{
|
||||
File::IOFile file(SConfig::GetInstance().m_strSRAM, "wb");
|
||||
auto& sram = Core::System::GetInstance().GetSRAM();
|
||||
file.WriteArray(&sram, 1);
|
||||
}
|
||||
}
|
||||
|
||||
void DoState(PointerWrap& p)
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "Core/CoreTiming.h"
|
||||
|
||||
class PointerWrap;
|
||||
struct Sram;
|
||||
|
||||
namespace CoreTiming
|
||||
{
|
||||
@ -51,7 +52,7 @@ constexpr bool IsMemcardSlot(Slot slot)
|
||||
u8 SlotToEXIChannel(Slot slot);
|
||||
u8 SlotToEXIDevice(Slot slot);
|
||||
|
||||
void Init();
|
||||
void Init(const Sram* override_sram);
|
||||
void Shutdown();
|
||||
void DoState(PointerWrap& p);
|
||||
void PauseAndLock(bool doLock, bool unpauseOnUnlock);
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include "Core/HW/SystemTimers.h"
|
||||
#include "Core/Movie.h"
|
||||
#include "Core/NetPlayProto.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
#include "DiscIO/Enums.h"
|
||||
|
||||
@ -129,28 +130,25 @@ CEXIIPL::CEXIIPL()
|
||||
LoadFontFile((File::GetSysDirectory() + GC_SYS_DIR + DIR_SEP + FONT_WINDOWS_1252), 0x1fcf00);
|
||||
}
|
||||
|
||||
auto& sram = Core::System::GetInstance().GetSRAM();
|
||||
|
||||
// Clear RTC
|
||||
g_SRAM.rtc = 0;
|
||||
sram.rtc = 0;
|
||||
|
||||
// We Overwrite language selection here since it's possible on the GC to change the language as
|
||||
// you please
|
||||
g_SRAM.settings.language = Config::Get(Config::MAIN_GC_LANGUAGE);
|
||||
g_SRAM.settings.rtc_bias = 0;
|
||||
FixSRAMChecksums();
|
||||
sram.settings.language = Config::Get(Config::MAIN_GC_LANGUAGE);
|
||||
sram.settings.rtc_bias = 0;
|
||||
FixSRAMChecksums(&sram);
|
||||
}
|
||||
|
||||
CEXIIPL::~CEXIIPL()
|
||||
{
|
||||
// SRAM
|
||||
if (!g_SRAM_netplay_initialized)
|
||||
{
|
||||
File::IOFile file(SConfig::GetInstance().m_strSRAM, "wb");
|
||||
file.WriteArray(&g_SRAM, 1);
|
||||
}
|
||||
}
|
||||
CEXIIPL::~CEXIIPL() = default;
|
||||
|
||||
void CEXIIPL::DoState(PointerWrap& p)
|
||||
{
|
||||
p.Do(g_SRAM);
|
||||
auto& sram = Core::System::GetInstance().GetSRAM();
|
||||
|
||||
p.Do(sram);
|
||||
p.Do(g_rtc_flags);
|
||||
p.Do(m_command);
|
||||
p.Do(m_command_bytes_received);
|
||||
@ -253,7 +251,8 @@ void CEXIIPL::SetCS(int cs)
|
||||
|
||||
void CEXIIPL::UpdateRTC()
|
||||
{
|
||||
g_SRAM.rtc = GetEmulatedTime(GC_EPOCH);
|
||||
auto& sram = Core::System::GetInstance().GetSRAM();
|
||||
sram.rtc = GetEmulatedTime(GC_EPOCH);
|
||||
}
|
||||
|
||||
bool CEXIIPL::IsPresent() const
|
||||
@ -343,11 +342,12 @@ void CEXIIPL::TransferByte(u8& data)
|
||||
}
|
||||
else if (IN_RANGE(SRAM))
|
||||
{
|
||||
auto& sram = Core::System::GetInstance().GetSRAM();
|
||||
u32 dev_addr = DEV_ADDR_CURSOR(SRAM);
|
||||
if (m_command.is_write())
|
||||
g_SRAM[dev_addr] = data;
|
||||
sram[dev_addr] = data;
|
||||
else
|
||||
data = g_SRAM[dev_addr];
|
||||
data = sram[dev_addr];
|
||||
}
|
||||
else if (IN_RANGE(UART))
|
||||
{
|
||||
|
@ -34,6 +34,7 @@
|
||||
#include "Core/HW/Sram.h"
|
||||
#include "Core/HW/SystemTimers.h"
|
||||
#include "Core/Movie.h"
|
||||
#include "Core/System.h"
|
||||
#include "DiscIO/Enums.h"
|
||||
|
||||
namespace ExpansionInterface
|
||||
@ -141,7 +142,8 @@ CEXIMemoryCard::CEXIMemoryCard(const Slot slot, bool gci_folder,
|
||||
m_memory_card_size = m_memory_card->GetCardId() * SIZE_TO_Mb;
|
||||
std::array<u8, 20> header{};
|
||||
m_memory_card->Read(0, static_cast<s32>(header.size()), header.data());
|
||||
SetCardFlashID(header.data(), m_card_slot);
|
||||
auto& sram = Core::System::GetInstance().GetSRAM();
|
||||
SetCardFlashID(&sram, header.data(), m_card_slot);
|
||||
}
|
||||
|
||||
std::pair<std::string /* path */, bool /* migrate */>
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "Core/HW/EXI/EXI_DeviceIPL.h"
|
||||
#include "Core/HW/GCMemcard/GCMemcard.h"
|
||||
#include "Core/HW/Sram.h"
|
||||
#include "Core/System.h"
|
||||
|
||||
#define SIZE_TO_Mb (1024 * 8 * 16)
|
||||
#define MC_HDR_SIZE 0xA000
|
||||
@ -59,10 +60,11 @@ MemoryCard::MemoryCard(const std::string& filename, ExpansionInterface::Slot car
|
||||
m_memcard_data = std::make_unique<u8[]>(m_memory_card_size);
|
||||
|
||||
// Fills in the first 5 blocks (MC_HDR_SIZE bytes)
|
||||
const CardFlashId& flash_id = g_SRAM.settings_ex.flash_id[Memcard::SLOT_A];
|
||||
auto& sram = Core::System::GetInstance().GetSRAM();
|
||||
const CardFlashId& flash_id = sram.settings_ex.flash_id[Memcard::SLOT_A];
|
||||
const bool shift_jis = m_filename.find(".JAP.raw") != std::string::npos;
|
||||
const u32 rtc_bias = g_SRAM.settings.rtc_bias;
|
||||
const u32 sram_language = static_cast<u32>(g_SRAM.settings.language);
|
||||
const u32 rtc_bias = sram.settings.rtc_bias;
|
||||
const u32 sram_language = static_cast<u32>(sram.settings.language);
|
||||
const u64 format_time =
|
||||
Common::Timer::GetLocalTimeSinceJan1970() - ExpansionInterface::CEXIIPL::GC_EPOCH;
|
||||
Memcard::GCMemcard::Format(&m_memcard_data[0], flash_id, size_mbits, shift_jis, rtc_bias,
|
||||
|
@ -31,7 +31,7 @@
|
||||
|
||||
namespace HW
|
||||
{
|
||||
void Init()
|
||||
void Init(const Sram* override_sram)
|
||||
{
|
||||
CoreTiming::Init();
|
||||
SystemTimers::PreInit();
|
||||
@ -43,7 +43,7 @@ void Init()
|
||||
VideoInterface::Init();
|
||||
SerialInterface::Init();
|
||||
ProcessorInterface::Init();
|
||||
ExpansionInterface::Init(); // Needs to be initialized before Memory
|
||||
ExpansionInterface::Init(override_sram); // Needs to be initialized before Memory
|
||||
HSP::Init();
|
||||
Memory::Init(); // Needs to be initialized before AddressSpace
|
||||
AddressSpace::Init();
|
||||
|
@ -4,10 +4,11 @@
|
||||
#pragma once
|
||||
|
||||
class PointerWrap;
|
||||
struct Sram;
|
||||
|
||||
namespace HW
|
||||
{
|
||||
void Init();
|
||||
void Init(const Sram* override_sram);
|
||||
void Shutdown();
|
||||
void DoState(PointerWrap& p);
|
||||
} // namespace HW
|
||||
|
@ -9,7 +9,6 @@
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/Swap.h"
|
||||
|
||||
#include "Core/ConfigManager.h"
|
||||
#include "Core/HW/EXI/EXI.h"
|
||||
|
||||
// English
|
||||
@ -58,24 +57,24 @@ const SRAM sram_dump_german = {{
|
||||
}};
|
||||
#endif
|
||||
|
||||
void InitSRAM()
|
||||
void InitSRAM(Sram* sram, const std::string& filename)
|
||||
{
|
||||
File::IOFile file(SConfig::GetInstance().m_strSRAM, "rb");
|
||||
File::IOFile file(filename, "rb");
|
||||
if (file)
|
||||
{
|
||||
if (!file.ReadArray(&g_SRAM, 1))
|
||||
if (!file.ReadArray(sram, 1))
|
||||
{
|
||||
ERROR_LOG_FMT(EXPANSIONINTERFACE, "EXI IPL-DEV: Could not read all of SRAM");
|
||||
g_SRAM = sram_dump;
|
||||
*sram = sram_dump;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
g_SRAM = sram_dump;
|
||||
*sram = sram_dump;
|
||||
}
|
||||
}
|
||||
|
||||
void SetCardFlashID(const u8* buffer, ExpansionInterface::Slot card_slot)
|
||||
void SetCardFlashID(Sram* sram, const u8* buffer, ExpansionInterface::Slot card_slot)
|
||||
{
|
||||
u8 card_index;
|
||||
switch (card_slot)
|
||||
@ -96,25 +95,25 @@ void SetCardFlashID(const u8* buffer, ExpansionInterface::Slot card_slot)
|
||||
for (int i = 0; i < 12; i++)
|
||||
{
|
||||
rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16);
|
||||
csum += g_SRAM.settings_ex.flash_id[card_index][i] = buffer[i] - ((u8)rand & 0xff);
|
||||
csum += sram->settings_ex.flash_id[card_index][i] = buffer[i] - ((u8)rand & 0xff);
|
||||
rand = (((rand * (u64)0x0000000041c64e6dULL) + (u64)0x0000000000003039ULL) >> 16);
|
||||
rand &= (u64)0x0000000000007fffULL;
|
||||
}
|
||||
g_SRAM.settings_ex.flash_id_checksum[card_index] = csum ^ 0xFF;
|
||||
sram->settings_ex.flash_id_checksum[card_index] = csum ^ 0xFF;
|
||||
}
|
||||
|
||||
void FixSRAMChecksums()
|
||||
void FixSRAMChecksums(Sram* sram)
|
||||
{
|
||||
// 16bit big-endian additive checksum
|
||||
u16 checksum = 0;
|
||||
u16 checksum_inv = 0;
|
||||
for (auto p = reinterpret_cast<u16*>(&g_SRAM.settings.rtc_bias);
|
||||
p != reinterpret_cast<u16*>(&g_SRAM.settings_ex); p++)
|
||||
for (auto p = reinterpret_cast<u16*>(&sram->settings.rtc_bias);
|
||||
p != reinterpret_cast<u16*>(&sram->settings_ex); p++)
|
||||
{
|
||||
u16 value = Common::FromBigEndian(*p);
|
||||
checksum += value;
|
||||
checksum_inv += ~value;
|
||||
}
|
||||
g_SRAM.settings.checksum = checksum;
|
||||
g_SRAM.settings.checksum_inv = checksum_inv;
|
||||
sram->settings.checksum = checksum;
|
||||
sram->settings.checksum_inv = checksum_inv;
|
||||
}
|
||||
|
@ -34,6 +34,7 @@ distribution.
|
||||
#pragma once
|
||||
|
||||
#include <array>
|
||||
#include <string>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/Swap.h"
|
||||
@ -133,9 +134,6 @@ static_assert(sizeof(Sram) == 0x44);
|
||||
|
||||
#pragma pack(pop)
|
||||
|
||||
void InitSRAM();
|
||||
void SetCardFlashID(const u8* buffer, ExpansionInterface::Slot card_slot);
|
||||
void FixSRAMChecksums();
|
||||
|
||||
extern Sram g_SRAM;
|
||||
extern bool g_SRAM_netplay_initialized;
|
||||
void InitSRAM(Sram* sram, const std::string& filename);
|
||||
void SetCardFlashID(Sram* sram, const u8* buffer, ExpansionInterface::Slot card_slot);
|
||||
void FixSRAMChecksums(Sram* sram);
|
||||
|
@ -432,10 +432,6 @@ void NetPlayClient::OnData(sf::Packet& packet)
|
||||
OnDesyncDetected(packet);
|
||||
break;
|
||||
|
||||
case MessageID::SyncGCSRAM:
|
||||
OnSyncGCSRAM(packet);
|
||||
break;
|
||||
|
||||
case MessageID::SyncSaveData:
|
||||
OnSyncSaveData(packet);
|
||||
break;
|
||||
@ -635,7 +631,7 @@ void NetPlayClient::OnGBAConfig(sf::Packet& packet)
|
||||
std::tie(old_config.has_rom, old_config.title, old_config.hash))
|
||||
{
|
||||
m_dialog->OnMsgChangeGBARom(static_cast<int>(i), config);
|
||||
m_net_settings.m_GBARomPaths[i] =
|
||||
m_net_settings.gba_rom_paths[i] =
|
||||
config.has_rom ?
|
||||
m_dialog->FindGBARomPath(config.hash, config.title, static_cast<int>(i)) :
|
||||
"";
|
||||
@ -809,92 +805,94 @@ void NetPlayClient::OnStartGame(sf::Packet& packet)
|
||||
INFO_LOG_FMT(NETPLAY, "Start of game {}", m_selected_game.game_id);
|
||||
|
||||
packet >> m_current_game;
|
||||
packet >> m_net_settings.m_CPUthread;
|
||||
packet >> m_net_settings.m_CPUcore;
|
||||
packet >> m_net_settings.m_EnableCheats;
|
||||
packet >> m_net_settings.m_SelectedLanguage;
|
||||
packet >> m_net_settings.m_OverrideRegionSettings;
|
||||
packet >> m_net_settings.m_DSPEnableJIT;
|
||||
packet >> m_net_settings.m_DSPHLE;
|
||||
packet >> m_net_settings.m_WriteToMemcard;
|
||||
packet >> m_net_settings.m_RAMOverrideEnable;
|
||||
packet >> m_net_settings.m_Mem1Size;
|
||||
packet >> m_net_settings.m_Mem2Size;
|
||||
packet >> m_net_settings.m_FallbackRegion;
|
||||
packet >> m_net_settings.m_AllowSDWrites;
|
||||
packet >> m_net_settings.m_CopyWiiSave;
|
||||
packet >> m_net_settings.m_OCEnable;
|
||||
packet >> m_net_settings.m_OCFactor;
|
||||
packet >> m_net_settings.cpu_thread;
|
||||
packet >> m_net_settings.cpu_core;
|
||||
packet >> m_net_settings.enable_cheats;
|
||||
packet >> m_net_settings.selected_language;
|
||||
packet >> m_net_settings.override_region_settings;
|
||||
packet >> m_net_settings.dsp_enable_jit;
|
||||
packet >> m_net_settings.dsp_hle;
|
||||
packet >> m_net_settings.write_to_memcard;
|
||||
packet >> m_net_settings.ram_override_enable;
|
||||
packet >> m_net_settings.mem1_size;
|
||||
packet >> m_net_settings.mem2_size;
|
||||
packet >> m_net_settings.fallback_region;
|
||||
packet >> m_net_settings.allow_sd_writes;
|
||||
packet >> m_net_settings.copy_wii_save;
|
||||
packet >> m_net_settings.oc_enable;
|
||||
packet >> m_net_settings.oc_factor;
|
||||
|
||||
for (auto slot : ExpansionInterface::SLOTS)
|
||||
packet >> m_net_settings.m_EXIDevice[slot];
|
||||
packet >> m_net_settings.exi_device[slot];
|
||||
|
||||
packet >> m_net_settings.m_MemcardSizeOverride;
|
||||
packet >> m_net_settings.memcard_size_override;
|
||||
|
||||
for (u32& value : m_net_settings.m_SYSCONFSettings)
|
||||
for (u32& value : m_net_settings.sysconf_settings)
|
||||
packet >> value;
|
||||
|
||||
packet >> m_net_settings.m_EFBAccessEnable;
|
||||
packet >> m_net_settings.m_BBoxEnable;
|
||||
packet >> m_net_settings.m_ForceProgressive;
|
||||
packet >> m_net_settings.m_EFBToTextureEnable;
|
||||
packet >> m_net_settings.m_XFBToTextureEnable;
|
||||
packet >> m_net_settings.m_DisableCopyToVRAM;
|
||||
packet >> m_net_settings.m_ImmediateXFBEnable;
|
||||
packet >> m_net_settings.m_EFBEmulateFormatChanges;
|
||||
packet >> m_net_settings.m_SafeTextureCacheColorSamples;
|
||||
packet >> m_net_settings.m_PerfQueriesEnable;
|
||||
packet >> m_net_settings.m_FloatExceptions;
|
||||
packet >> m_net_settings.m_DivideByZeroExceptions;
|
||||
packet >> m_net_settings.m_FPRF;
|
||||
packet >> m_net_settings.m_AccurateNaNs;
|
||||
packet >> m_net_settings.m_DisableICache;
|
||||
packet >> m_net_settings.m_SyncOnSkipIdle;
|
||||
packet >> m_net_settings.m_SyncGPU;
|
||||
packet >> m_net_settings.m_SyncGpuMaxDistance;
|
||||
packet >> m_net_settings.m_SyncGpuMinDistance;
|
||||
packet >> m_net_settings.m_SyncGpuOverclock;
|
||||
packet >> m_net_settings.m_JITFollowBranch;
|
||||
packet >> m_net_settings.m_FastDiscSpeed;
|
||||
packet >> m_net_settings.m_MMU;
|
||||
packet >> m_net_settings.m_Fastmem;
|
||||
packet >> m_net_settings.m_SkipIPL;
|
||||
packet >> m_net_settings.m_LoadIPLDump;
|
||||
packet >> m_net_settings.m_VertexRounding;
|
||||
packet >> m_net_settings.m_InternalResolution;
|
||||
packet >> m_net_settings.m_EFBScaledCopy;
|
||||
packet >> m_net_settings.m_FastDepthCalc;
|
||||
packet >> m_net_settings.m_EnablePixelLighting;
|
||||
packet >> m_net_settings.m_WidescreenHack;
|
||||
packet >> m_net_settings.m_ForceFiltering;
|
||||
packet >> m_net_settings.m_MaxAnisotropy;
|
||||
packet >> m_net_settings.m_ForceTrueColor;
|
||||
packet >> m_net_settings.m_DisableCopyFilter;
|
||||
packet >> m_net_settings.m_DisableFog;
|
||||
packet >> m_net_settings.m_ArbitraryMipmapDetection;
|
||||
packet >> m_net_settings.m_ArbitraryMipmapDetectionThreshold;
|
||||
packet >> m_net_settings.m_EnableGPUTextureDecoding;
|
||||
packet >> m_net_settings.m_DeferEFBCopies;
|
||||
packet >> m_net_settings.m_EFBAccessTileSize;
|
||||
packet >> m_net_settings.m_EFBAccessDeferInvalidation;
|
||||
packet >> m_net_settings.m_StrictSettingsSync;
|
||||
packet >> m_net_settings.efb_access_enable;
|
||||
packet >> m_net_settings.bbox_enable;
|
||||
packet >> m_net_settings.force_progressive;
|
||||
packet >> m_net_settings.efb_to_texture_enable;
|
||||
packet >> m_net_settings.xfb_to_texture_enable;
|
||||
packet >> m_net_settings.disable_copy_to_vram;
|
||||
packet >> m_net_settings.immediate_xfb_enable;
|
||||
packet >> m_net_settings.efb_emulate_format_changes;
|
||||
packet >> m_net_settings.safe_texture_cache_color_samples;
|
||||
packet >> m_net_settings.perf_queries_enable;
|
||||
packet >> m_net_settings.float_exceptions;
|
||||
packet >> m_net_settings.divide_by_zero_exceptions;
|
||||
packet >> m_net_settings.fprf;
|
||||
packet >> m_net_settings.accurate_nans;
|
||||
packet >> m_net_settings.disable_icache;
|
||||
packet >> m_net_settings.sync_on_skip_idle;
|
||||
packet >> m_net_settings.sync_gpu;
|
||||
packet >> m_net_settings.sync_gpu_max_distance;
|
||||
packet >> m_net_settings.sync_gpu_min_distance;
|
||||
packet >> m_net_settings.sync_gpu_overclock;
|
||||
packet >> m_net_settings.jit_follow_branch;
|
||||
packet >> m_net_settings.fast_disc_speed;
|
||||
packet >> m_net_settings.mmu;
|
||||
packet >> m_net_settings.fastmem;
|
||||
packet >> m_net_settings.skip_ipl;
|
||||
packet >> m_net_settings.load_ipl_dump;
|
||||
packet >> m_net_settings.vertex_rounding;
|
||||
packet >> m_net_settings.internal_resolution;
|
||||
packet >> m_net_settings.efb_scaled_copy;
|
||||
packet >> m_net_settings.fast_depth_calc;
|
||||
packet >> m_net_settings.enable_pixel_lighting;
|
||||
packet >> m_net_settings.widescreen_hack;
|
||||
packet >> m_net_settings.force_filtering;
|
||||
packet >> m_net_settings.max_anisotropy;
|
||||
packet >> m_net_settings.force_true_color;
|
||||
packet >> m_net_settings.disable_copy_filter;
|
||||
packet >> m_net_settings.disable_fog;
|
||||
packet >> m_net_settings.arbitrary_mipmap_detection;
|
||||
packet >> m_net_settings.arbitrary_mipmap_detection_threshold;
|
||||
packet >> m_net_settings.enable_gpu_texture_decoding;
|
||||
packet >> m_net_settings.defer_efb_copies;
|
||||
packet >> m_net_settings.efb_access_tile_size;
|
||||
packet >> m_net_settings.efb_access_defer_invalidation;
|
||||
packet >> m_net_settings.strict_settings_sync;
|
||||
|
||||
m_initial_rtc = Common::PacketReadU64(packet);
|
||||
|
||||
packet >> m_net_settings.m_SyncSaveData;
|
||||
packet >> m_net_settings.m_SaveDataRegion;
|
||||
packet >> m_net_settings.m_SyncCodes;
|
||||
packet >> m_net_settings.m_SyncAllWiiSaves;
|
||||
packet >> m_net_settings.sync_save_data;
|
||||
packet >> m_net_settings.save_data_region;
|
||||
packet >> m_net_settings.sync_codes;
|
||||
packet >> m_net_settings.sync_all_wii_saves;
|
||||
|
||||
for (int& extension : m_net_settings.m_WiimoteExtension)
|
||||
for (int& extension : m_net_settings.wiimote_extension)
|
||||
packet >> extension;
|
||||
|
||||
packet >> m_net_settings.m_GolfMode;
|
||||
packet >> m_net_settings.m_UseFMA;
|
||||
packet >> m_net_settings.m_HideRemoteGBAs;
|
||||
packet >> m_net_settings.golf_mode;
|
||||
packet >> m_net_settings.use_fma;
|
||||
packet >> m_net_settings.hide_remote_gbas;
|
||||
|
||||
m_net_settings.m_IsHosting = m_local_player->IsHost();
|
||||
m_net_settings.m_HostInputAuthority = m_host_input_authority;
|
||||
for (size_t i = 0; i < sizeof(m_net_settings.sram); ++i)
|
||||
packet >> m_net_settings.sram[i];
|
||||
|
||||
m_net_settings.is_hosting = m_local_player->IsHost();
|
||||
}
|
||||
|
||||
m_dialog->OnMsgStartGame();
|
||||
@ -910,6 +908,7 @@ void NetPlayClient::OnStopGame(sf::Packet& packet)
|
||||
|
||||
void NetPlayClient::OnPowerButton()
|
||||
{
|
||||
InvokeStop();
|
||||
m_dialog->OnMsgPowerButton();
|
||||
}
|
||||
|
||||
@ -960,20 +959,6 @@ void NetPlayClient::OnDesyncDetected(sf::Packet& packet)
|
||||
m_dialog->OnDesync(frame, player);
|
||||
}
|
||||
|
||||
void NetPlayClient::OnSyncGCSRAM(sf::Packet& packet)
|
||||
{
|
||||
const size_t sram_settings_len = sizeof(g_SRAM) - offsetof(Sram, settings);
|
||||
u8 sram[sram_settings_len];
|
||||
for (u8& cell : sram)
|
||||
packet >> cell;
|
||||
|
||||
{
|
||||
std::lock_guard lkg(m_crit.game);
|
||||
memcpy(&g_SRAM.settings, sram, sram_settings_len);
|
||||
g_SRAM_netplay_initialized = true;
|
||||
}
|
||||
}
|
||||
|
||||
void NetPlayClient::OnSyncSaveData(sf::Packet& packet)
|
||||
{
|
||||
SyncSaveDataID sub_id;
|
||||
@ -2048,6 +2033,22 @@ u64 NetPlayClient::GetInitialRTCValue() const
|
||||
return m_initial_rtc;
|
||||
}
|
||||
|
||||
bool NetPlayClient::WaitForWiimoteBuffer(int _number)
|
||||
{
|
||||
while (m_wiimote_buffer[_number].Size() == 0)
|
||||
{
|
||||
if (!m_is_running.IsSet())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// wait for receiving thread to push some data
|
||||
m_wii_pad_event.Wait();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
// called from ---CPU--- thread
|
||||
bool NetPlayClient::WiimoteUpdate(int _number, u8* data, const std::size_t size, u8 reporting_mode)
|
||||
{
|
||||
@ -2073,16 +2074,8 @@ bool NetPlayClient::WiimoteUpdate(int _number, u8* data, const std::size_t size,
|
||||
|
||||
} // unlock players
|
||||
|
||||
while (m_wiimote_buffer[_number].Size() == 0)
|
||||
{
|
||||
if (!m_is_running.IsSet())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// wait for receiving thread to push some data
|
||||
m_wii_pad_event.Wait();
|
||||
}
|
||||
if (!WaitForWiimoteBuffer(_number))
|
||||
return false;
|
||||
|
||||
m_wiimote_buffer[_number].Pop(nw);
|
||||
|
||||
@ -2093,16 +2086,8 @@ bool NetPlayClient::WiimoteUpdate(int _number, u8* data, const std::size_t size,
|
||||
u32 tries = 0;
|
||||
while (nw.report_id != reporting_mode)
|
||||
{
|
||||
while (m_wiimote_buffer[_number].Size() == 0)
|
||||
{
|
||||
if (!m_is_running.IsSet())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
// wait for receiving thread to push some data
|
||||
m_wii_pad_event.Wait();
|
||||
}
|
||||
if (!WaitForWiimoteBuffer(_number))
|
||||
return false;
|
||||
|
||||
m_wiimote_buffer[_number].Pop(nw);
|
||||
|
||||
@ -2244,8 +2229,7 @@ void NetPlayClient::SendPadHostPoll(const PadIndex pad_num)
|
||||
SendAsync(std::move(packet));
|
||||
}
|
||||
|
||||
// called from ---GUI--- thread and ---NETPLAY--- thread (client side)
|
||||
bool NetPlayClient::StopGame()
|
||||
void NetPlayClient::InvokeStop()
|
||||
{
|
||||
m_is_running.Clear();
|
||||
|
||||
@ -2254,6 +2238,12 @@ bool NetPlayClient::StopGame()
|
||||
m_wii_pad_event.Set();
|
||||
m_first_pad_status_received_event.Set();
|
||||
m_wait_on_input_event.Set();
|
||||
}
|
||||
|
||||
// called from ---GUI--- thread and ---NETPLAY--- thread (client side)
|
||||
bool NetPlayClient::StopGame()
|
||||
{
|
||||
InvokeStop();
|
||||
|
||||
NetPlay_Disable();
|
||||
|
||||
@ -2269,13 +2259,7 @@ void NetPlayClient::Stop()
|
||||
if (!m_is_running.IsSet())
|
||||
return;
|
||||
|
||||
m_is_running.Clear();
|
||||
|
||||
// stop waiting for input
|
||||
m_gc_pad_event.Set();
|
||||
m_wii_pad_event.Set();
|
||||
m_first_pad_status_received_event.Set();
|
||||
m_wait_on_input_event.Set();
|
||||
InvokeStop();
|
||||
|
||||
// Tell the server to stop if we have a pad mapped in game.
|
||||
if (LocalPlayerHasControllerMapped())
|
||||
@ -2300,7 +2284,7 @@ void NetPlayClient::SendPowerButtonEvent()
|
||||
|
||||
void NetPlayClient::RequestGolfControl(const PlayerId pid)
|
||||
{
|
||||
if (!m_host_input_authority || !m_net_settings.m_GolfMode)
|
||||
if (!m_host_input_authority || !m_net_settings.golf_mode)
|
||||
return;
|
||||
|
||||
sf::Packet packet;
|
||||
@ -2402,7 +2386,7 @@ void NetPlayClient::SendGameStatus()
|
||||
for (size_t i = 0; i < 4; ++i)
|
||||
{
|
||||
if (m_gba_config[i].enabled && m_gba_config[i].has_rom &&
|
||||
m_net_settings.m_GBARomPaths[i].empty())
|
||||
m_net_settings.gba_rom_paths[i].empty())
|
||||
{
|
||||
result = SyncIdentifierComparison::DifferentGame;
|
||||
}
|
||||
@ -2592,7 +2576,7 @@ bool IsSyncingAllWiiSaves()
|
||||
std::lock_guard lk(crit_netplay_client);
|
||||
|
||||
if (netplay_client)
|
||||
return netplay_client->GetNetSettings().m_SyncAllWiiSaves;
|
||||
return netplay_client->GetNetSettings().sync_all_wii_saves;
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -2602,14 +2586,14 @@ void SetupWiimotes()
|
||||
ASSERT(IsNetPlayRunning());
|
||||
const NetSettings& netplay_settings = netplay_client->GetNetSettings();
|
||||
const PadMappingArray& wiimote_map = netplay_client->GetWiimoteMapping();
|
||||
for (size_t i = 0; i < netplay_settings.m_WiimoteExtension.size(); i++)
|
||||
for (size_t i = 0; i < netplay_settings.wiimote_extension.size(); i++)
|
||||
{
|
||||
if (wiimote_map[i] > 0)
|
||||
{
|
||||
static_cast<ControllerEmu::Attachments*>(
|
||||
static_cast<WiimoteEmu::Wiimote*>(Wiimote::GetConfig()->GetController(int(i)))
|
||||
->GetWiimoteGroup(WiimoteEmu::WiimoteGroup::Attachments))
|
||||
->SetSelectedAttachment(netplay_settings.m_WiimoteExtension[i]);
|
||||
->SetSelectedAttachment(netplay_settings.wiimote_extension[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -2618,7 +2602,7 @@ std::string GetGBASavePath(int pad_num)
|
||||
{
|
||||
std::lock_guard lk(crit_netplay_client);
|
||||
|
||||
if (!netplay_client || netplay_client->GetNetSettings().m_IsHosting)
|
||||
if (!netplay_client || netplay_client->GetNetSettings().is_hosting)
|
||||
{
|
||||
#ifdef HAS_LIBMGBA
|
||||
std::string rom_path = Config::Get(Config::MAIN_GBA_ROM_PATHS[pad_num]);
|
||||
@ -2628,7 +2612,7 @@ std::string GetGBASavePath(int pad_num)
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!netplay_client->GetNetSettings().m_SyncSaveData)
|
||||
if (!netplay_client->GetNetSettings().sync_save_data)
|
||||
return {};
|
||||
|
||||
return fmt::format("{}{}{}.sav", File::GetUserPath(D_GBAUSER_IDX), GBA_SAVE_NETPLAY, pad_num + 1);
|
||||
@ -2664,7 +2648,7 @@ PadDetails GetPadDetails(int pad_num)
|
||||
}
|
||||
res.is_local = netplay_client->IsLocalPlayer(pad_map[pad_num]);
|
||||
res.local_pad = res.is_local ? local_pad : netplay_client->NumLocalPads() + non_local_pad;
|
||||
res.hide_gba = !res.is_local && netplay_client->GetNetSettings().m_HideRemoteGBAs &&
|
||||
res.hide_gba = !res.is_local && netplay_client->GetNetSettings().hide_remote_gbas &&
|
||||
netplay_client->LocalPlayerHasControllerMapped();
|
||||
return res;
|
||||
}
|
||||
|
@ -117,6 +117,7 @@ public:
|
||||
// Called from the GUI thread.
|
||||
bool IsConnected() const { return m_is_connected; }
|
||||
bool StartGame(const std::string& path);
|
||||
void InvokeStop();
|
||||
bool StopGame();
|
||||
void Stop();
|
||||
bool ChangeGame(const std::string& game);
|
||||
@ -252,6 +253,8 @@ private:
|
||||
void DisplayPlayersPing();
|
||||
u32 GetPlayersMaxPing() const;
|
||||
|
||||
bool WaitForWiimoteBuffer(int _number);
|
||||
|
||||
void OnData(sf::Packet& packet);
|
||||
void OnPlayerJoin(sf::Packet& packet);
|
||||
void OnPlayerLeave(sf::Packet& packet);
|
||||
@ -278,7 +281,6 @@ private:
|
||||
void OnPing(sf::Packet& packet);
|
||||
void OnPlayerPingData(sf::Packet& packet);
|
||||
void OnDesyncDetected(sf::Packet& packet);
|
||||
void OnSyncGCSRAM(sf::Packet& packet);
|
||||
void OnSyncSaveData(sf::Packet& packet);
|
||||
void OnSyncSaveDataNotify(sf::Packet& packet);
|
||||
void OnSyncSaveDataRaw(sf::Packet& packet);
|
||||
|
@ -12,6 +12,7 @@
|
||||
#include "Core/Config/SYSCONFSettings.h"
|
||||
#include "Core/HW/EXI/EXI.h"
|
||||
#include "Core/HW/EXI/EXI_Device.h"
|
||||
#include "Core/HW/Sram.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
@ -30,85 +31,86 @@ namespace NetPlay
|
||||
{
|
||||
struct NetSettings
|
||||
{
|
||||
bool m_CPUthread = false;
|
||||
PowerPC::CPUCore m_CPUcore{};
|
||||
bool m_EnableCheats = false;
|
||||
int m_SelectedLanguage = 0;
|
||||
bool m_OverrideRegionSettings = false;
|
||||
bool m_DSPHLE = false;
|
||||
bool m_DSPEnableJIT = false;
|
||||
bool m_WriteToMemcard = false;
|
||||
bool m_RAMOverrideEnable = false;
|
||||
u32 m_Mem1Size = 0;
|
||||
u32 m_Mem2Size = 0;
|
||||
DiscIO::Region m_FallbackRegion{};
|
||||
bool m_AllowSDWrites = false;
|
||||
bool m_CopyWiiSave = false;
|
||||
bool m_OCEnable = false;
|
||||
float m_OCFactor = 0;
|
||||
Common::EnumMap<ExpansionInterface::EXIDeviceType, ExpansionInterface::MAX_SLOT> m_EXIDevice{};
|
||||
int m_MemcardSizeOverride = -1;
|
||||
bool cpu_thread = false;
|
||||
PowerPC::CPUCore cpu_core{};
|
||||
bool enable_cheats = false;
|
||||
int selected_language = 0;
|
||||
bool override_region_settings = false;
|
||||
bool dsp_hle = false;
|
||||
bool dsp_enable_jit = false;
|
||||
bool write_to_memcard = false;
|
||||
bool ram_override_enable = false;
|
||||
u32 mem1_size = 0;
|
||||
u32 mem2_size = 0;
|
||||
DiscIO::Region fallback_region{};
|
||||
bool allow_sd_writes = false;
|
||||
bool copy_wii_save = false;
|
||||
bool oc_enable = false;
|
||||
float oc_factor = 0;
|
||||
Common::EnumMap<ExpansionInterface::EXIDeviceType, ExpansionInterface::MAX_SLOT> exi_device{};
|
||||
int memcard_size_override = -1;
|
||||
|
||||
std::array<u32, Config::SYSCONF_SETTINGS.size()> m_SYSCONFSettings{};
|
||||
std::array<u32, Config::SYSCONF_SETTINGS.size()> sysconf_settings{};
|
||||
|
||||
bool m_EFBAccessEnable = false;
|
||||
bool m_BBoxEnable = false;
|
||||
bool m_ForceProgressive = false;
|
||||
bool m_EFBToTextureEnable = false;
|
||||
bool m_XFBToTextureEnable = false;
|
||||
bool m_DisableCopyToVRAM = false;
|
||||
bool m_ImmediateXFBEnable = false;
|
||||
bool m_EFBEmulateFormatChanges = false;
|
||||
int m_SafeTextureCacheColorSamples = 0;
|
||||
bool m_PerfQueriesEnable = false;
|
||||
bool m_FloatExceptions = false;
|
||||
bool m_DivideByZeroExceptions = false;
|
||||
bool m_FPRF = false;
|
||||
bool m_AccurateNaNs = false;
|
||||
bool m_DisableICache = false;
|
||||
bool m_SyncOnSkipIdle = false;
|
||||
bool m_SyncGPU = false;
|
||||
int m_SyncGpuMaxDistance = 0;
|
||||
int m_SyncGpuMinDistance = 0;
|
||||
float m_SyncGpuOverclock = 0;
|
||||
bool m_JITFollowBranch = false;
|
||||
bool m_FastDiscSpeed = false;
|
||||
bool m_MMU = false;
|
||||
bool m_Fastmem = false;
|
||||
bool m_SkipIPL = false;
|
||||
bool m_LoadIPLDump = false;
|
||||
bool m_VertexRounding = false;
|
||||
int m_InternalResolution = 0;
|
||||
bool m_EFBScaledCopy = false;
|
||||
bool m_FastDepthCalc = false;
|
||||
bool m_EnablePixelLighting = false;
|
||||
bool m_WidescreenHack = false;
|
||||
bool m_ForceFiltering = false;
|
||||
int m_MaxAnisotropy = 0;
|
||||
bool m_ForceTrueColor = false;
|
||||
bool m_DisableCopyFilter = false;
|
||||
bool m_DisableFog = false;
|
||||
bool m_ArbitraryMipmapDetection = false;
|
||||
float m_ArbitraryMipmapDetectionThreshold = 0;
|
||||
bool m_EnableGPUTextureDecoding = false;
|
||||
bool m_DeferEFBCopies = false;
|
||||
int m_EFBAccessTileSize = 0;
|
||||
bool m_EFBAccessDeferInvalidation = false;
|
||||
bool efb_access_enable = false;
|
||||
bool bbox_enable = false;
|
||||
bool force_progressive = false;
|
||||
bool efb_to_texture_enable = false;
|
||||
bool xfb_to_texture_enable = false;
|
||||
bool disable_copy_to_vram = false;
|
||||
bool immediate_xfb_enable = false;
|
||||
bool efb_emulate_format_changes = false;
|
||||
int safe_texture_cache_color_samples = 0;
|
||||
bool perf_queries_enable = false;
|
||||
bool float_exceptions = false;
|
||||
bool divide_by_zero_exceptions = false;
|
||||
bool fprf = false;
|
||||
bool accurate_nans = false;
|
||||
bool disable_icache = false;
|
||||
bool sync_on_skip_idle = false;
|
||||
bool sync_gpu = false;
|
||||
int sync_gpu_max_distance = 0;
|
||||
int sync_gpu_min_distance = 0;
|
||||
float sync_gpu_overclock = 0;
|
||||
bool jit_follow_branch = false;
|
||||
bool fast_disc_speed = false;
|
||||
bool mmu = false;
|
||||
bool fastmem = false;
|
||||
bool skip_ipl = false;
|
||||
bool load_ipl_dump = false;
|
||||
bool vertex_rounding = false;
|
||||
int internal_resolution = 0;
|
||||
bool efb_scaled_copy = false;
|
||||
bool fast_depth_calc = false;
|
||||
bool enable_pixel_lighting = false;
|
||||
bool widescreen_hack = false;
|
||||
bool force_filtering = false;
|
||||
int max_anisotropy = 0;
|
||||
bool force_true_color = false;
|
||||
bool disable_copy_filter = false;
|
||||
bool disable_fog = false;
|
||||
bool arbitrary_mipmap_detection = false;
|
||||
float arbitrary_mipmap_detection_threshold = 0;
|
||||
bool enable_gpu_texture_decoding = false;
|
||||
bool defer_efb_copies = false;
|
||||
int efb_access_tile_size = 0;
|
||||
bool efb_access_defer_invalidation = false;
|
||||
|
||||
bool m_StrictSettingsSync = false;
|
||||
bool m_SyncSaveData = false;
|
||||
bool m_SyncCodes = false;
|
||||
std::string m_SaveDataRegion;
|
||||
bool m_SyncAllWiiSaves = false;
|
||||
std::array<int, 4> m_WiimoteExtension{};
|
||||
bool m_GolfMode = false;
|
||||
bool m_UseFMA = false;
|
||||
bool m_HideRemoteGBAs = false;
|
||||
bool strict_settings_sync = false;
|
||||
bool sync_save_data = false;
|
||||
bool sync_codes = false;
|
||||
std::string save_data_region;
|
||||
bool sync_all_wii_saves = false;
|
||||
std::array<int, 4> wiimote_extension{};
|
||||
bool golf_mode = false;
|
||||
bool use_fma = false;
|
||||
bool hide_remote_gbas = false;
|
||||
|
||||
Sram sram;
|
||||
|
||||
// These aren't sent over the network directly
|
||||
bool m_IsHosting = false;
|
||||
bool m_HostInputAuthority = false;
|
||||
std::array<std::string, 4> m_GBARomPaths{};
|
||||
bool is_hosting = false;
|
||||
std::array<std::string, 4> gba_rom_paths{};
|
||||
};
|
||||
|
||||
struct NetTraversalConfig
|
||||
@ -181,7 +183,6 @@ enum class MessageID : u8
|
||||
Pong = 0xE1,
|
||||
PlayerPingData = 0xE2,
|
||||
|
||||
SyncGCSRAM = 0xF0,
|
||||
SyncSaveData = 0xF1,
|
||||
SyncCodes = 0xF2,
|
||||
};
|
||||
|
@ -862,7 +862,7 @@ unsigned int NetPlayServer::OnData(sf::Packet& packet, Client& player)
|
||||
if (!m_players.count(pid) || !PlayerHasControllerMapped(player.pid))
|
||||
break;
|
||||
|
||||
if (m_host_input_authority && m_settings.m_GolfMode && m_pending_golfer == 0 &&
|
||||
if (m_host_input_authority && m_settings.golf_mode && m_pending_golfer == 0 &&
|
||||
m_current_golfer != pid && PlayerHasControllerMapped(pid))
|
||||
{
|
||||
m_pending_golfer = pid;
|
||||
@ -1254,22 +1254,22 @@ bool NetPlayServer::SetupNetSettings()
|
||||
ConfigLoaders::GenerateLocalGameConfigLoader(game->GetGameID(), game->GetRevision()));
|
||||
|
||||
// Copy all relevant settings
|
||||
settings.m_CPUthread = Config::Get(Config::MAIN_CPU_THREAD);
|
||||
settings.m_CPUcore = Config::Get(Config::MAIN_CPU_CORE);
|
||||
settings.m_EnableCheats = Config::Get(Config::MAIN_ENABLE_CHEATS);
|
||||
settings.m_SelectedLanguage = Config::Get(Config::MAIN_GC_LANGUAGE);
|
||||
settings.m_OverrideRegionSettings = Config::Get(Config::MAIN_OVERRIDE_REGION_SETTINGS);
|
||||
settings.m_DSPHLE = Config::Get(Config::MAIN_DSP_HLE);
|
||||
settings.m_DSPEnableJIT = Config::Get(Config::MAIN_DSP_JIT);
|
||||
settings.m_WriteToMemcard = Config::Get(Config::NETPLAY_WRITE_SAVE_DATA);
|
||||
settings.m_RAMOverrideEnable = Config::Get(Config::MAIN_RAM_OVERRIDE_ENABLE);
|
||||
settings.m_Mem1Size = Config::Get(Config::MAIN_MEM1_SIZE);
|
||||
settings.m_Mem2Size = Config::Get(Config::MAIN_MEM2_SIZE);
|
||||
settings.m_FallbackRegion = Config::Get(Config::MAIN_FALLBACK_REGION);
|
||||
settings.m_AllowSDWrites = Config::Get(Config::MAIN_ALLOW_SD_WRITES);
|
||||
settings.m_CopyWiiSave = Config::Get(Config::NETPLAY_LOAD_WII_SAVE);
|
||||
settings.m_OCEnable = Config::Get(Config::MAIN_OVERCLOCK_ENABLE);
|
||||
settings.m_OCFactor = Config::Get(Config::MAIN_OVERCLOCK);
|
||||
settings.cpu_thread = Config::Get(Config::MAIN_CPU_THREAD);
|
||||
settings.cpu_core = Config::Get(Config::MAIN_CPU_CORE);
|
||||
settings.enable_cheats = Config::Get(Config::MAIN_ENABLE_CHEATS);
|
||||
settings.selected_language = Config::Get(Config::MAIN_GC_LANGUAGE);
|
||||
settings.override_region_settings = Config::Get(Config::MAIN_OVERRIDE_REGION_SETTINGS);
|
||||
settings.dsp_hle = Config::Get(Config::MAIN_DSP_HLE);
|
||||
settings.dsp_enable_jit = Config::Get(Config::MAIN_DSP_JIT);
|
||||
settings.write_to_memcard = Config::Get(Config::NETPLAY_WRITE_SAVE_DATA);
|
||||
settings.ram_override_enable = Config::Get(Config::MAIN_RAM_OVERRIDE_ENABLE);
|
||||
settings.mem1_size = Config::Get(Config::MAIN_MEM1_SIZE);
|
||||
settings.mem2_size = Config::Get(Config::MAIN_MEM2_SIZE);
|
||||
settings.fallback_region = Config::Get(Config::MAIN_FALLBACK_REGION);
|
||||
settings.allow_sd_writes = Config::Get(Config::MAIN_ALLOW_SD_WRITES);
|
||||
settings.copy_wii_save = Config::Get(Config::NETPLAY_LOAD_WII_SAVE);
|
||||
settings.oc_enable = Config::Get(Config::MAIN_OVERCLOCK_ENABLE);
|
||||
settings.oc_factor = Config::Get(Config::MAIN_OVERCLOCK);
|
||||
|
||||
for (ExpansionInterface::Slot slot : ExpansionInterface::SLOTS)
|
||||
{
|
||||
@ -1283,75 +1283,75 @@ bool NetPlayServer::SetupNetSettings()
|
||||
{
|
||||
device = Config::Get(Config::GetInfoForEXIDevice(slot));
|
||||
}
|
||||
settings.m_EXIDevice[slot] = device;
|
||||
settings.exi_device[slot] = device;
|
||||
}
|
||||
|
||||
settings.m_MemcardSizeOverride = Config::Get(Config::MAIN_MEMORY_CARD_SIZE);
|
||||
settings.memcard_size_override = Config::Get(Config::MAIN_MEMORY_CARD_SIZE);
|
||||
|
||||
for (size_t i = 0; i < Config::SYSCONF_SETTINGS.size(); ++i)
|
||||
{
|
||||
std::visit(
|
||||
[&](auto* info) {
|
||||
static_assert(sizeof(info->GetDefaultValue()) <= sizeof(u32));
|
||||
settings.m_SYSCONFSettings[i] = static_cast<u32>(Config::Get(*info));
|
||||
settings.sysconf_settings[i] = static_cast<u32>(Config::Get(*info));
|
||||
},
|
||||
Config::SYSCONF_SETTINGS[i].config_info);
|
||||
}
|
||||
|
||||
settings.m_EFBAccessEnable = Config::Get(Config::GFX_HACK_EFB_ACCESS_ENABLE);
|
||||
settings.m_BBoxEnable = Config::Get(Config::GFX_HACK_BBOX_ENABLE);
|
||||
settings.m_ForceProgressive = Config::Get(Config::GFX_HACK_FORCE_PROGRESSIVE);
|
||||
settings.m_EFBToTextureEnable = Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM);
|
||||
settings.m_XFBToTextureEnable = Config::Get(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM);
|
||||
settings.m_DisableCopyToVRAM = Config::Get(Config::GFX_HACK_DISABLE_COPY_TO_VRAM);
|
||||
settings.m_ImmediateXFBEnable = Config::Get(Config::GFX_HACK_IMMEDIATE_XFB);
|
||||
settings.m_EFBEmulateFormatChanges = Config::Get(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES);
|
||||
settings.m_SafeTextureCacheColorSamples =
|
||||
settings.efb_access_enable = Config::Get(Config::GFX_HACK_EFB_ACCESS_ENABLE);
|
||||
settings.bbox_enable = Config::Get(Config::GFX_HACK_BBOX_ENABLE);
|
||||
settings.force_progressive = Config::Get(Config::GFX_HACK_FORCE_PROGRESSIVE);
|
||||
settings.efb_to_texture_enable = Config::Get(Config::GFX_HACK_SKIP_EFB_COPY_TO_RAM);
|
||||
settings.xfb_to_texture_enable = Config::Get(Config::GFX_HACK_SKIP_XFB_COPY_TO_RAM);
|
||||
settings.disable_copy_to_vram = Config::Get(Config::GFX_HACK_DISABLE_COPY_TO_VRAM);
|
||||
settings.immediate_xfb_enable = Config::Get(Config::GFX_HACK_IMMEDIATE_XFB);
|
||||
settings.efb_emulate_format_changes = Config::Get(Config::GFX_HACK_EFB_EMULATE_FORMAT_CHANGES);
|
||||
settings.safe_texture_cache_color_samples =
|
||||
Config::Get(Config::GFX_SAFE_TEXTURE_CACHE_COLOR_SAMPLES);
|
||||
settings.m_PerfQueriesEnable = Config::Get(Config::GFX_PERF_QUERIES_ENABLE);
|
||||
settings.m_FloatExceptions = Config::Get(Config::MAIN_FLOAT_EXCEPTIONS);
|
||||
settings.m_DivideByZeroExceptions = Config::Get(Config::MAIN_DIVIDE_BY_ZERO_EXCEPTIONS);
|
||||
settings.m_FPRF = Config::Get(Config::MAIN_FPRF);
|
||||
settings.m_AccurateNaNs = Config::Get(Config::MAIN_ACCURATE_NANS);
|
||||
settings.m_DisableICache = Config::Get(Config::MAIN_DISABLE_ICACHE);
|
||||
settings.m_SyncOnSkipIdle = Config::Get(Config::MAIN_SYNC_ON_SKIP_IDLE);
|
||||
settings.m_SyncGPU = Config::Get(Config::MAIN_SYNC_GPU);
|
||||
settings.m_SyncGpuMaxDistance = Config::Get(Config::MAIN_SYNC_GPU_MAX_DISTANCE);
|
||||
settings.m_SyncGpuMinDistance = Config::Get(Config::MAIN_SYNC_GPU_MIN_DISTANCE);
|
||||
settings.m_SyncGpuOverclock = Config::Get(Config::MAIN_SYNC_GPU_OVERCLOCK);
|
||||
settings.m_JITFollowBranch = Config::Get(Config::MAIN_JIT_FOLLOW_BRANCH);
|
||||
settings.m_FastDiscSpeed = Config::Get(Config::MAIN_FAST_DISC_SPEED);
|
||||
settings.m_MMU = Config::Get(Config::MAIN_MMU);
|
||||
settings.m_Fastmem = Config::Get(Config::MAIN_FASTMEM);
|
||||
settings.m_SkipIPL = Config::Get(Config::MAIN_SKIP_IPL) || !DoAllPlayersHaveIPLDump();
|
||||
settings.m_LoadIPLDump = Config::Get(Config::SESSION_LOAD_IPL_DUMP) && DoAllPlayersHaveIPLDump();
|
||||
settings.m_VertexRounding = Config::Get(Config::GFX_HACK_VERTEX_ROUNDING);
|
||||
settings.m_InternalResolution = Config::Get(Config::GFX_EFB_SCALE);
|
||||
settings.m_EFBScaledCopy = Config::Get(Config::GFX_HACK_COPY_EFB_SCALED);
|
||||
settings.m_FastDepthCalc = Config::Get(Config::GFX_FAST_DEPTH_CALC);
|
||||
settings.m_EnablePixelLighting = Config::Get(Config::GFX_ENABLE_PIXEL_LIGHTING);
|
||||
settings.m_WidescreenHack = Config::Get(Config::GFX_WIDESCREEN_HACK);
|
||||
settings.m_ForceFiltering = Config::Get(Config::GFX_ENHANCE_FORCE_FILTERING);
|
||||
settings.m_MaxAnisotropy = Config::Get(Config::GFX_ENHANCE_MAX_ANISOTROPY);
|
||||
settings.m_ForceTrueColor = Config::Get(Config::GFX_ENHANCE_FORCE_TRUE_COLOR);
|
||||
settings.m_DisableCopyFilter = Config::Get(Config::GFX_ENHANCE_DISABLE_COPY_FILTER);
|
||||
settings.m_DisableFog = Config::Get(Config::GFX_DISABLE_FOG);
|
||||
settings.m_ArbitraryMipmapDetection = Config::Get(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION);
|
||||
settings.m_ArbitraryMipmapDetectionThreshold =
|
||||
settings.perf_queries_enable = Config::Get(Config::GFX_PERF_QUERIES_ENABLE);
|
||||
settings.float_exceptions = Config::Get(Config::MAIN_FLOAT_EXCEPTIONS);
|
||||
settings.divide_by_zero_exceptions = Config::Get(Config::MAIN_DIVIDE_BY_ZERO_EXCEPTIONS);
|
||||
settings.fprf = Config::Get(Config::MAIN_FPRF);
|
||||
settings.accurate_nans = Config::Get(Config::MAIN_ACCURATE_NANS);
|
||||
settings.disable_icache = Config::Get(Config::MAIN_DISABLE_ICACHE);
|
||||
settings.sync_on_skip_idle = Config::Get(Config::MAIN_SYNC_ON_SKIP_IDLE);
|
||||
settings.sync_gpu = Config::Get(Config::MAIN_SYNC_GPU);
|
||||
settings.sync_gpu_max_distance = Config::Get(Config::MAIN_SYNC_GPU_MAX_DISTANCE);
|
||||
settings.sync_gpu_min_distance = Config::Get(Config::MAIN_SYNC_GPU_MIN_DISTANCE);
|
||||
settings.sync_gpu_overclock = Config::Get(Config::MAIN_SYNC_GPU_OVERCLOCK);
|
||||
settings.jit_follow_branch = Config::Get(Config::MAIN_JIT_FOLLOW_BRANCH);
|
||||
settings.fast_disc_speed = Config::Get(Config::MAIN_FAST_DISC_SPEED);
|
||||
settings.mmu = Config::Get(Config::MAIN_MMU);
|
||||
settings.fastmem = Config::Get(Config::MAIN_FASTMEM);
|
||||
settings.skip_ipl = Config::Get(Config::MAIN_SKIP_IPL) || !DoAllPlayersHaveIPLDump();
|
||||
settings.load_ipl_dump = Config::Get(Config::SESSION_LOAD_IPL_DUMP) && DoAllPlayersHaveIPLDump();
|
||||
settings.vertex_rounding = Config::Get(Config::GFX_HACK_VERTEX_ROUNDING);
|
||||
settings.internal_resolution = Config::Get(Config::GFX_EFB_SCALE);
|
||||
settings.efb_scaled_copy = Config::Get(Config::GFX_HACK_COPY_EFB_SCALED);
|
||||
settings.fast_depth_calc = Config::Get(Config::GFX_FAST_DEPTH_CALC);
|
||||
settings.enable_pixel_lighting = Config::Get(Config::GFX_ENABLE_PIXEL_LIGHTING);
|
||||
settings.widescreen_hack = Config::Get(Config::GFX_WIDESCREEN_HACK);
|
||||
settings.force_filtering = Config::Get(Config::GFX_ENHANCE_FORCE_FILTERING);
|
||||
settings.max_anisotropy = Config::Get(Config::GFX_ENHANCE_MAX_ANISOTROPY);
|
||||
settings.force_true_color = Config::Get(Config::GFX_ENHANCE_FORCE_TRUE_COLOR);
|
||||
settings.disable_copy_filter = Config::Get(Config::GFX_ENHANCE_DISABLE_COPY_FILTER);
|
||||
settings.disable_fog = Config::Get(Config::GFX_DISABLE_FOG);
|
||||
settings.arbitrary_mipmap_detection = Config::Get(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION);
|
||||
settings.arbitrary_mipmap_detection_threshold =
|
||||
Config::Get(Config::GFX_ENHANCE_ARBITRARY_MIPMAP_DETECTION_THRESHOLD);
|
||||
settings.m_EnableGPUTextureDecoding = Config::Get(Config::GFX_ENABLE_GPU_TEXTURE_DECODING);
|
||||
settings.m_DeferEFBCopies = Config::Get(Config::GFX_HACK_DEFER_EFB_COPIES);
|
||||
settings.m_EFBAccessTileSize = Config::Get(Config::GFX_HACK_EFB_ACCESS_TILE_SIZE);
|
||||
settings.m_EFBAccessDeferInvalidation = Config::Get(Config::GFX_HACK_EFB_DEFER_INVALIDATION);
|
||||
settings.enable_gpu_texture_decoding = Config::Get(Config::GFX_ENABLE_GPU_TEXTURE_DECODING);
|
||||
settings.defer_efb_copies = Config::Get(Config::GFX_HACK_DEFER_EFB_COPIES);
|
||||
settings.efb_access_tile_size = Config::Get(Config::GFX_HACK_EFB_ACCESS_TILE_SIZE);
|
||||
settings.efb_access_defer_invalidation = Config::Get(Config::GFX_HACK_EFB_DEFER_INVALIDATION);
|
||||
|
||||
settings.m_StrictSettingsSync = Config::Get(Config::NETPLAY_STRICT_SETTINGS_SYNC);
|
||||
settings.m_SyncSaveData = Config::Get(Config::NETPLAY_SYNC_SAVES);
|
||||
settings.m_SyncCodes = Config::Get(Config::NETPLAY_SYNC_CODES);
|
||||
settings.m_SyncAllWiiSaves =
|
||||
settings.strict_settings_sync = Config::Get(Config::NETPLAY_STRICT_SETTINGS_SYNC);
|
||||
settings.sync_save_data = Config::Get(Config::NETPLAY_SYNC_SAVES);
|
||||
settings.sync_codes = Config::Get(Config::NETPLAY_SYNC_CODES);
|
||||
settings.sync_all_wii_saves =
|
||||
Config::Get(Config::NETPLAY_SYNC_ALL_WII_SAVES) && Config::Get(Config::NETPLAY_SYNC_SAVES);
|
||||
settings.m_GolfMode = Config::Get(Config::NETPLAY_NETWORK_MODE) == "golf";
|
||||
settings.m_UseFMA = DoAllPlayersHaveHardwareFMA();
|
||||
settings.m_HideRemoteGBAs = Config::Get(Config::NETPLAY_HIDE_REMOTE_GBAS);
|
||||
settings.golf_mode = Config::Get(Config::NETPLAY_NETWORK_MODE) == "golf";
|
||||
settings.use_fma = DoAllPlayersHaveHardwareFMA();
|
||||
settings.hide_remote_gbas = Config::Get(Config::NETPLAY_HIDE_REMOTE_GBAS);
|
||||
|
||||
// Unload GameINI to restore things to normal
|
||||
Config::RemoveLayer(Config::LayerType::GlobalGame);
|
||||
@ -1382,7 +1382,7 @@ bool NetPlayServer::RequestStartGame()
|
||||
|
||||
bool start_now = true;
|
||||
|
||||
if (m_settings.m_SyncSaveData && m_players.size() > 1)
|
||||
if (m_settings.sync_save_data && m_players.size() > 1)
|
||||
{
|
||||
start_now = false;
|
||||
m_start_pending = true;
|
||||
@ -1395,7 +1395,7 @@ bool NetPlayServer::RequestStartGame()
|
||||
}
|
||||
|
||||
// Check To Send Codes to Clients
|
||||
if (m_settings.m_SyncCodes && m_players.size() > 1)
|
||||
if (m_settings.sync_codes && m_players.size() > 1)
|
||||
{
|
||||
start_now = false;
|
||||
m_start_pending = true;
|
||||
@ -1436,101 +1436,90 @@ bool NetPlayServer::StartGame()
|
||||
const std::string region = Config::GetDirectoryForRegion(
|
||||
Config::ToGameCubeRegion(m_dialog->FindGameFile(m_selected_game_identifier)->GetRegion()));
|
||||
|
||||
// sync GC SRAM with clients
|
||||
if (!g_SRAM_netplay_initialized)
|
||||
{
|
||||
SConfig::GetInstance().m_strSRAM = File::GetUserPath(F_GCSRAM_IDX);
|
||||
InitSRAM();
|
||||
g_SRAM_netplay_initialized = true;
|
||||
}
|
||||
sf::Packet srampac;
|
||||
srampac << MessageID::SyncGCSRAM;
|
||||
for (size_t i = 0; i < sizeof(g_SRAM) - offsetof(Sram, settings); ++i)
|
||||
{
|
||||
srampac << g_SRAM[offsetof(Sram, settings) + i];
|
||||
}
|
||||
SendAsyncToClients(std::move(srampac), 1);
|
||||
// load host's GC SRAM
|
||||
SConfig::GetInstance().m_strSRAM = File::GetUserPath(F_GCSRAM_IDX);
|
||||
InitSRAM(&m_settings.sram, SConfig::GetInstance().m_strSRAM);
|
||||
|
||||
// tell clients to start game
|
||||
sf::Packet spac;
|
||||
spac << MessageID::StartGame;
|
||||
spac << m_current_game;
|
||||
spac << m_settings.m_CPUthread;
|
||||
spac << m_settings.m_CPUcore;
|
||||
spac << m_settings.m_EnableCheats;
|
||||
spac << m_settings.m_SelectedLanguage;
|
||||
spac << m_settings.m_OverrideRegionSettings;
|
||||
spac << m_settings.m_DSPEnableJIT;
|
||||
spac << m_settings.m_DSPHLE;
|
||||
spac << m_settings.m_WriteToMemcard;
|
||||
spac << m_settings.m_RAMOverrideEnable;
|
||||
spac << m_settings.m_Mem1Size;
|
||||
spac << m_settings.m_Mem2Size;
|
||||
spac << m_settings.m_FallbackRegion;
|
||||
spac << m_settings.m_AllowSDWrites;
|
||||
spac << m_settings.m_CopyWiiSave;
|
||||
spac << m_settings.m_OCEnable;
|
||||
spac << m_settings.m_OCFactor;
|
||||
spac << m_settings.cpu_thread;
|
||||
spac << m_settings.cpu_core;
|
||||
spac << m_settings.enable_cheats;
|
||||
spac << m_settings.selected_language;
|
||||
spac << m_settings.override_region_settings;
|
||||
spac << m_settings.dsp_enable_jit;
|
||||
spac << m_settings.dsp_hle;
|
||||
spac << m_settings.write_to_memcard;
|
||||
spac << m_settings.ram_override_enable;
|
||||
spac << m_settings.mem1_size;
|
||||
spac << m_settings.mem2_size;
|
||||
spac << m_settings.fallback_region;
|
||||
spac << m_settings.allow_sd_writes;
|
||||
spac << m_settings.copy_wii_save;
|
||||
spac << m_settings.oc_enable;
|
||||
spac << m_settings.oc_factor;
|
||||
|
||||
for (auto slot : ExpansionInterface::SLOTS)
|
||||
spac << static_cast<int>(m_settings.m_EXIDevice[slot]);
|
||||
spac << static_cast<int>(m_settings.exi_device[slot]);
|
||||
|
||||
spac << m_settings.m_MemcardSizeOverride;
|
||||
spac << m_settings.memcard_size_override;
|
||||
|
||||
for (u32 value : m_settings.m_SYSCONFSettings)
|
||||
for (u32 value : m_settings.sysconf_settings)
|
||||
spac << value;
|
||||
|
||||
spac << m_settings.m_EFBAccessEnable;
|
||||
spac << m_settings.m_BBoxEnable;
|
||||
spac << m_settings.m_ForceProgressive;
|
||||
spac << m_settings.m_EFBToTextureEnable;
|
||||
spac << m_settings.m_XFBToTextureEnable;
|
||||
spac << m_settings.m_DisableCopyToVRAM;
|
||||
spac << m_settings.m_ImmediateXFBEnable;
|
||||
spac << m_settings.m_EFBEmulateFormatChanges;
|
||||
spac << m_settings.m_SafeTextureCacheColorSamples;
|
||||
spac << m_settings.m_PerfQueriesEnable;
|
||||
spac << m_settings.m_FloatExceptions;
|
||||
spac << m_settings.m_DivideByZeroExceptions;
|
||||
spac << m_settings.m_FPRF;
|
||||
spac << m_settings.m_AccurateNaNs;
|
||||
spac << m_settings.m_DisableICache;
|
||||
spac << m_settings.m_SyncOnSkipIdle;
|
||||
spac << m_settings.m_SyncGPU;
|
||||
spac << m_settings.m_SyncGpuMaxDistance;
|
||||
spac << m_settings.m_SyncGpuMinDistance;
|
||||
spac << m_settings.m_SyncGpuOverclock;
|
||||
spac << m_settings.m_JITFollowBranch;
|
||||
spac << m_settings.m_FastDiscSpeed;
|
||||
spac << m_settings.m_MMU;
|
||||
spac << m_settings.m_Fastmem;
|
||||
spac << m_settings.m_SkipIPL;
|
||||
spac << m_settings.m_LoadIPLDump;
|
||||
spac << m_settings.m_VertexRounding;
|
||||
spac << m_settings.m_InternalResolution;
|
||||
spac << m_settings.m_EFBScaledCopy;
|
||||
spac << m_settings.m_FastDepthCalc;
|
||||
spac << m_settings.m_EnablePixelLighting;
|
||||
spac << m_settings.m_WidescreenHack;
|
||||
spac << m_settings.m_ForceFiltering;
|
||||
spac << m_settings.m_MaxAnisotropy;
|
||||
spac << m_settings.m_ForceTrueColor;
|
||||
spac << m_settings.m_DisableCopyFilter;
|
||||
spac << m_settings.m_DisableFog;
|
||||
spac << m_settings.m_ArbitraryMipmapDetection;
|
||||
spac << m_settings.m_ArbitraryMipmapDetectionThreshold;
|
||||
spac << m_settings.m_EnableGPUTextureDecoding;
|
||||
spac << m_settings.m_DeferEFBCopies;
|
||||
spac << m_settings.m_EFBAccessTileSize;
|
||||
spac << m_settings.m_EFBAccessDeferInvalidation;
|
||||
spac << m_settings.m_StrictSettingsSync;
|
||||
spac << m_settings.efb_access_enable;
|
||||
spac << m_settings.bbox_enable;
|
||||
spac << m_settings.force_progressive;
|
||||
spac << m_settings.efb_to_texture_enable;
|
||||
spac << m_settings.xfb_to_texture_enable;
|
||||
spac << m_settings.disable_copy_to_vram;
|
||||
spac << m_settings.immediate_xfb_enable;
|
||||
spac << m_settings.efb_emulate_format_changes;
|
||||
spac << m_settings.safe_texture_cache_color_samples;
|
||||
spac << m_settings.perf_queries_enable;
|
||||
spac << m_settings.float_exceptions;
|
||||
spac << m_settings.divide_by_zero_exceptions;
|
||||
spac << m_settings.fprf;
|
||||
spac << m_settings.accurate_nans;
|
||||
spac << m_settings.disable_icache;
|
||||
spac << m_settings.sync_on_skip_idle;
|
||||
spac << m_settings.sync_gpu;
|
||||
spac << m_settings.sync_gpu_max_distance;
|
||||
spac << m_settings.sync_gpu_min_distance;
|
||||
spac << m_settings.sync_gpu_overclock;
|
||||
spac << m_settings.jit_follow_branch;
|
||||
spac << m_settings.fast_disc_speed;
|
||||
spac << m_settings.mmu;
|
||||
spac << m_settings.fastmem;
|
||||
spac << m_settings.skip_ipl;
|
||||
spac << m_settings.load_ipl_dump;
|
||||
spac << m_settings.vertex_rounding;
|
||||
spac << m_settings.internal_resolution;
|
||||
spac << m_settings.efb_scaled_copy;
|
||||
spac << m_settings.fast_depth_calc;
|
||||
spac << m_settings.enable_pixel_lighting;
|
||||
spac << m_settings.widescreen_hack;
|
||||
spac << m_settings.force_filtering;
|
||||
spac << m_settings.max_anisotropy;
|
||||
spac << m_settings.force_true_color;
|
||||
spac << m_settings.disable_copy_filter;
|
||||
spac << m_settings.disable_fog;
|
||||
spac << m_settings.arbitrary_mipmap_detection;
|
||||
spac << m_settings.arbitrary_mipmap_detection_threshold;
|
||||
spac << m_settings.enable_gpu_texture_decoding;
|
||||
spac << m_settings.defer_efb_copies;
|
||||
spac << m_settings.efb_access_tile_size;
|
||||
spac << m_settings.efb_access_defer_invalidation;
|
||||
spac << m_settings.strict_settings_sync;
|
||||
spac << initial_rtc;
|
||||
spac << m_settings.m_SyncSaveData;
|
||||
spac << m_settings.sync_save_data;
|
||||
spac << region;
|
||||
spac << m_settings.m_SyncCodes;
|
||||
spac << m_settings.m_SyncAllWiiSaves;
|
||||
spac << m_settings.sync_codes;
|
||||
spac << m_settings.sync_all_wii_saves;
|
||||
|
||||
for (size_t i = 0; i < m_settings.m_WiimoteExtension.size(); i++)
|
||||
for (size_t i = 0; i < m_settings.wiimote_extension.size(); i++)
|
||||
{
|
||||
const int extension =
|
||||
static_cast<ControllerEmu::Attachments*>(
|
||||
@ -1540,9 +1529,12 @@ bool NetPlayServer::StartGame()
|
||||
spac << extension;
|
||||
}
|
||||
|
||||
spac << m_settings.m_GolfMode;
|
||||
spac << m_settings.m_UseFMA;
|
||||
spac << m_settings.m_HideRemoteGBAs;
|
||||
spac << m_settings.golf_mode;
|
||||
spac << m_settings.use_fma;
|
||||
spac << m_settings.hide_remote_gbas;
|
||||
|
||||
for (size_t i = 0; i < sizeof(m_settings.sram); ++i)
|
||||
spac << m_settings.sram[i];
|
||||
|
||||
SendAsyncToClients(std::move(spac));
|
||||
|
||||
@ -1574,7 +1566,7 @@ bool NetPlayServer::SyncSaveData()
|
||||
|
||||
for (ExpansionInterface::Slot slot : ExpansionInterface::MEMCARD_SLOTS)
|
||||
{
|
||||
if (m_settings.m_EXIDevice[slot] == ExpansionInterface::EXIDeviceType::MemoryCard ||
|
||||
if (m_settings.exi_device[slot] == ExpansionInterface::EXIDeviceType::MemoryCard ||
|
||||
Config::Get(Config::GetInfoForEXIDevice(slot)) ==
|
||||
ExpansionInterface::EXIDeviceType::MemoryCardFolder)
|
||||
{
|
||||
@ -1590,7 +1582,7 @@ bool NetPlayServer::SyncSaveData()
|
||||
}
|
||||
|
||||
bool wii_save = false;
|
||||
if (m_settings.m_CopyWiiSave && (game->GetPlatform() == DiscIO::Platform::WiiDisc ||
|
||||
if (m_settings.copy_wii_save && (game->GetPlatform() == DiscIO::Platform::WiiDisc ||
|
||||
game->GetPlatform() == DiscIO::Platform::WiiWAD ||
|
||||
game->GetPlatform() == DiscIO::Platform::ELFOrDOL))
|
||||
{
|
||||
@ -1635,9 +1627,9 @@ bool NetPlayServer::SyncSaveData()
|
||||
{
|
||||
const bool is_slot_a = slot == ExpansionInterface::Slot::A;
|
||||
|
||||
if (m_settings.m_EXIDevice[slot] == ExpansionInterface::EXIDeviceType::MemoryCard)
|
||||
if (m_settings.exi_device[slot] == ExpansionInterface::EXIDeviceType::MemoryCard)
|
||||
{
|
||||
const int size_override = m_settings.m_MemcardSizeOverride;
|
||||
const int size_override = m_settings.memcard_size_override;
|
||||
const u16 card_size_mbits =
|
||||
size_override >= 0 && size_override <= 4 ?
|
||||
static_cast<u16>(Memcard::MBIT_SIZE_MEMORY_CARD_59 << size_override) :
|
||||
@ -1703,7 +1695,7 @@ bool NetPlayServer::SyncSaveData()
|
||||
const auto configured_fs = IOS::HLE::FS::MakeFileSystem(IOS::HLE::FS::Location::Configured);
|
||||
|
||||
std::vector<std::pair<u64, WiiSave::StoragePointer>> saves;
|
||||
if (m_settings.m_SyncAllWiiSaves)
|
||||
if (m_settings.sync_all_wii_saves)
|
||||
{
|
||||
IOS::HLE::Kernel ios;
|
||||
for (const u64 title : ios.GetES()->GetInstalledTitles())
|
||||
|
@ -336,6 +336,7 @@ void JitArm64::mfspr(UGeckoInstruction inst)
|
||||
|
||||
ADD(Xresult, XA, Xresult, ArithOption(Xresult, ShiftType::LSR, 3));
|
||||
STR(IndexType::Unsigned, Xresult, PPC_REG, PPCSTATE_OFF_SPR(SPR_TL));
|
||||
static_assert((PPCSTATE_OFF_SPR(SPR_TL) & 0x7) == 0);
|
||||
|
||||
if (CanMergeNextInstructions(1))
|
||||
{
|
||||
|
@ -162,7 +162,8 @@ struct PowerPCState
|
||||
|
||||
// special purpose registers - controls quantizers, DMA, and lots of other misc extensions.
|
||||
// also for power management, but we don't care about that.
|
||||
u32 spr[1024]{};
|
||||
// JitArm64 needs 64-bit alignment for SPR_TL.
|
||||
alignas(8) u32 spr[1024]{};
|
||||
|
||||
// Storage for the stack pointer of the BLR optimization.
|
||||
u8* stored_stack_pointer = nullptr;
|
||||
|
@ -74,7 +74,7 @@ static std::recursive_mutex g_save_thread_mutex;
|
||||
static std::thread g_save_thread;
|
||||
|
||||
// Don't forget to increase this after doing changes on the savestate system
|
||||
constexpr u32 STATE_VERSION = 148; // Last changed in PR 10768
|
||||
constexpr u32 STATE_VERSION = 149; // Last changed in PR 10781
|
||||
|
||||
// Maps savestate versions to Dolphin versions.
|
||||
// Versions after 42 don't need to be added to this list,
|
||||
|
@ -10,6 +10,7 @@
|
||||
#include "Core/HW/AudioInterface.h"
|
||||
#include "Core/HW/DVD/DVDInterface.h"
|
||||
#include "Core/HW/DVD/DVDThread.h"
|
||||
#include "Core/HW/Sram.h"
|
||||
|
||||
namespace Core
|
||||
{
|
||||
@ -22,6 +23,7 @@ struct System::Impl
|
||||
AudioInterface::AudioInterfaceState m_audio_interface_state;
|
||||
DVDInterface::DVDInterfaceState m_dvd_interface_state;
|
||||
DVDThread::DVDThreadState m_dvd_thread_state;
|
||||
Sram m_sram;
|
||||
};
|
||||
|
||||
System::System() : m_impl{std::make_unique<Impl>()}
|
||||
@ -80,4 +82,9 @@ DVDThread::DVDThreadState& System::GetDVDThreadState() const
|
||||
{
|
||||
return m_impl->m_dvd_thread_state;
|
||||
}
|
||||
|
||||
Sram& System::GetSRAM() const
|
||||
{
|
||||
return m_impl->m_sram;
|
||||
}
|
||||
} // namespace Core
|
||||
|
@ -6,6 +6,7 @@
|
||||
#include <memory>
|
||||
|
||||
class SoundStream;
|
||||
struct Sram;
|
||||
|
||||
namespace AudioInterface
|
||||
{
|
||||
@ -56,6 +57,7 @@ public:
|
||||
AudioInterface::AudioInterfaceState& GetAudioInterfaceState() const;
|
||||
DVDInterface::DVDInterfaceState& GetDVDInterfaceState() const;
|
||||
DVDThread::DVDThreadState& GetDVDThreadState() const;
|
||||
Sram& GetSRAM() const;
|
||||
|
||||
private:
|
||||
System();
|
||||
|
@ -1432,8 +1432,9 @@ void VolumeVerifier::Finish()
|
||||
}
|
||||
else
|
||||
{
|
||||
Common::GetStringT("Problems with low severity were found. They will most "
|
||||
"likely not prevent the game from running.");
|
||||
m_result.summary_text =
|
||||
Common::GetStringT("Problems with low severity were found. They will most "
|
||||
"likely not prevent the game from running.");
|
||||
}
|
||||
break;
|
||||
case Severity::Medium:
|
||||
|
@ -13,12 +13,17 @@
|
||||
|
||||
#include "DolphinQt/Config/ControllerInterface/ControllerInterfaceWindow.h"
|
||||
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
|
||||
#include "DolphinQt/QtUtils/SignalBlocking.h"
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
||||
CommonControllersWidget::CommonControllersWidget(QWidget* parent) : QWidget(parent)
|
||||
{
|
||||
CreateLayout();
|
||||
LoadSettings();
|
||||
ConnectWidgets();
|
||||
|
||||
connect(&Settings::Instance(), &Settings::ConfigChanged, this,
|
||||
&CommonControllersWidget::LoadSettings);
|
||||
}
|
||||
|
||||
void CommonControllersWidget::CreateLayout()
|
||||
@ -59,7 +64,7 @@ void CommonControllersWidget::OnControllerInterfaceConfigure()
|
||||
|
||||
void CommonControllersWidget::LoadSettings()
|
||||
{
|
||||
m_common_bg_input->setChecked(Config::Get(Config::MAIN_INPUT_BACKGROUND_INPUT));
|
||||
SignalBlocking(m_common_bg_input)->setChecked(Config::Get(Config::MAIN_INPUT_BACKGROUND_INPUT));
|
||||
}
|
||||
|
||||
void CommonControllersWidget::SaveSettings()
|
||||
|
@ -26,23 +26,26 @@
|
||||
#include "DolphinQt/Config/Mapping/MappingWindow.h"
|
||||
#include "DolphinQt/QtUtils/ModalMessageBox.h"
|
||||
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
|
||||
#include "DolphinQt/QtUtils/SignalBlocking.h"
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
||||
#include "InputCommon/GCAdapter.h"
|
||||
|
||||
static const std::vector<std::pair<SerialInterface::SIDevices, const char*>> s_gc_types = {
|
||||
{SerialInterface::SIDEVICE_NONE, _trans("None")},
|
||||
{SerialInterface::SIDEVICE_GC_CONTROLLER, _trans("Standard Controller")},
|
||||
{SerialInterface::SIDEVICE_GC_METROID, _trans("Metroid Controller")},
|
||||
{SerialInterface::SIDEVICE_WIIU_ADAPTER, _trans("GameCube Adapter for Wii U")},
|
||||
{SerialInterface::SIDEVICE_GC_STEERING, _trans("Steering Wheel")},
|
||||
{SerialInterface::SIDEVICE_DANCEMAT, _trans("Dance Mat")},
|
||||
{SerialInterface::SIDEVICE_GC_TARUKONGA, _trans("DK Bongos")},
|
||||
using SIDeviceName = std::pair<SerialInterface::SIDevices, const char*>;
|
||||
static constexpr std::array s_gc_types = {
|
||||
SIDeviceName{SerialInterface::SIDEVICE_NONE, _trans("None")},
|
||||
SIDeviceName{SerialInterface::SIDEVICE_GC_CONTROLLER, _trans("Standard Controller")},
|
||||
SIDeviceName{SerialInterface::SIDEVICE_GC_METROID, _trans("Metroid Controller")},
|
||||
SIDeviceName{SerialInterface::SIDEVICE_WIIU_ADAPTER, _trans("GameCube Adapter for Wii U")},
|
||||
SIDeviceName{SerialInterface::SIDEVICE_GC_STEERING, _trans("Steering Wheel")},
|
||||
SIDeviceName{SerialInterface::SIDEVICE_DANCEMAT, _trans("Dance Mat")},
|
||||
SIDeviceName{SerialInterface::SIDEVICE_GC_TARUKONGA, _trans("DK Bongos")},
|
||||
#ifdef HAS_LIBMGBA
|
||||
{SerialInterface::SIDEVICE_GC_GBA_EMULATED, _trans("GBA (Integrated)")},
|
||||
SIDeviceName{SerialInterface::SIDEVICE_GC_GBA_EMULATED, _trans("GBA (Integrated)")},
|
||||
#endif
|
||||
{SerialInterface::SIDEVICE_GC_GBA, _trans("GBA (TCP)")},
|
||||
{SerialInterface::SIDEVICE_GC_KEYBOARD, _trans("Keyboard")}};
|
||||
SIDeviceName{SerialInterface::SIDEVICE_GC_GBA, _trans("GBA (TCP)")},
|
||||
SIDeviceName{SerialInterface::SIDEVICE_GC_KEYBOARD, _trans("Keyboard")},
|
||||
};
|
||||
|
||||
static std::optional<int> ToGCMenuIndex(const SerialInterface::SIDevices sidevice)
|
||||
{
|
||||
@ -59,16 +62,14 @@ static SerialInterface::SIDevices FromGCMenuIndex(const int menudevice)
|
||||
return s_gc_types[menudevice].first;
|
||||
}
|
||||
|
||||
static bool IsConfigurable(SerialInterface::SIDevices sidevice)
|
||||
{
|
||||
return sidevice != SerialInterface::SIDEVICE_NONE && sidevice != SerialInterface::SIDEVICE_GC_GBA;
|
||||
}
|
||||
|
||||
GamecubeControllersWidget::GamecubeControllersWidget(QWidget* parent) : QWidget(parent)
|
||||
{
|
||||
CreateLayout();
|
||||
LoadSettings();
|
||||
ConnectWidgets();
|
||||
|
||||
connect(&Settings::Instance(), &Settings::ConfigChanged, this,
|
||||
&GamecubeControllersWidget::LoadSettings);
|
||||
}
|
||||
|
||||
void GamecubeControllersWidget::CreateLayout()
|
||||
@ -105,43 +106,27 @@ void GamecubeControllersWidget::CreateLayout()
|
||||
|
||||
void GamecubeControllersWidget::ConnectWidgets()
|
||||
{
|
||||
for (size_t i = 0; i < m_gc_controller_boxes.size(); i++)
|
||||
for (size_t i = 0; i < m_gc_controller_boxes.size(); ++i)
|
||||
{
|
||||
connect(m_gc_controller_boxes[i], qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
&GamecubeControllersWidget::SaveSettings);
|
||||
connect(m_gc_controller_boxes[i], qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
&GamecubeControllersWidget::OnGCTypeChanged);
|
||||
connect(m_gc_buttons[i], &QPushButton::clicked, this,
|
||||
&GamecubeControllersWidget::OnGCPadConfigure);
|
||||
[this, i] {
|
||||
OnGCTypeChanged(i);
|
||||
SaveSettings();
|
||||
});
|
||||
connect(m_gc_buttons[i], &QPushButton::clicked, this, [this, i] { OnGCPadConfigure(i); });
|
||||
}
|
||||
}
|
||||
|
||||
void GamecubeControllersWidget::OnGCTypeChanged(int type)
|
||||
void GamecubeControllersWidget::OnGCTypeChanged(size_t index)
|
||||
{
|
||||
const auto* box = static_cast<QComboBox*>(QObject::sender());
|
||||
|
||||
for (size_t i = 0; i < m_gc_groups.size(); i++)
|
||||
{
|
||||
if (m_gc_controller_boxes[i] == box)
|
||||
{
|
||||
const SerialInterface::SIDevices si_device = FromGCMenuIndex(box->currentIndex());
|
||||
m_gc_buttons[i]->setEnabled(IsConfigurable(si_device));
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
SaveSettings();
|
||||
const SerialInterface::SIDevices si_device =
|
||||
FromGCMenuIndex(m_gc_controller_boxes[index]->currentIndex());
|
||||
m_gc_buttons[index]->setEnabled(si_device != SerialInterface::SIDEVICE_NONE &&
|
||||
si_device != SerialInterface::SIDEVICE_GC_GBA);
|
||||
}
|
||||
|
||||
void GamecubeControllersWidget::OnGCPadConfigure()
|
||||
void GamecubeControllersWidget::OnGCPadConfigure(size_t index)
|
||||
{
|
||||
size_t index;
|
||||
for (index = 0; index < m_gc_groups.size(); index++)
|
||||
{
|
||||
if (m_gc_buttons[index] == QObject::sender())
|
||||
break;
|
||||
}
|
||||
|
||||
MappingWindow::Type type;
|
||||
|
||||
switch (FromGCMenuIndex(m_gc_controller_boxes[index]->currentIndex()))
|
||||
@ -207,30 +192,32 @@ void GamecubeControllersWidget::LoadSettings()
|
||||
const std::optional<int> gc_index = ToGCMenuIndex(si_device);
|
||||
if (gc_index)
|
||||
{
|
||||
m_gc_controller_boxes[i]->setCurrentIndex(*gc_index);
|
||||
m_gc_buttons[i]->setEnabled(IsConfigurable(si_device));
|
||||
SignalBlocking(m_gc_controller_boxes[i])->setCurrentIndex(*gc_index);
|
||||
OnGCTypeChanged(i);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void GamecubeControllersWidget::SaveSettings()
|
||||
{
|
||||
for (size_t i = 0; i < m_gc_groups.size(); i++)
|
||||
{
|
||||
const int index = m_gc_controller_boxes[i]->currentIndex();
|
||||
const SerialInterface::SIDevices si_device = FromGCMenuIndex(index);
|
||||
Config::SetBaseOrCurrent(Config::GetInfoForSIDevice(static_cast<int>(i)), si_device);
|
||||
Config::ConfigChangeCallbackGuard config_guard;
|
||||
|
||||
if (Core::IsRunning())
|
||||
SerialInterface::ChangeDevice(si_device, static_cast<s32>(i));
|
||||
for (size_t i = 0; i < m_gc_groups.size(); ++i)
|
||||
{
|
||||
const SerialInterface::SIDevices si_device =
|
||||
FromGCMenuIndex(m_gc_controller_boxes[i]->currentIndex());
|
||||
Config::SetBaseOrCurrent(Config::GetInfoForSIDevice(static_cast<int>(i)), si_device);
|
||||
|
||||
m_gc_buttons[i]->setEnabled(IsConfigurable(si_device));
|
||||
if (Core::IsRunning())
|
||||
SerialInterface::ChangeDevice(si_device, static_cast<s32>(i));
|
||||
}
|
||||
|
||||
if (GCAdapter::UseAdapter())
|
||||
GCAdapter::StartScanThread();
|
||||
else
|
||||
GCAdapter::StopScanThread();
|
||||
}
|
||||
|
||||
if (GCAdapter::UseAdapter())
|
||||
GCAdapter::StartScanThread();
|
||||
else
|
||||
GCAdapter::StopScanThread();
|
||||
|
||||
SConfig::GetInstance().SaveSettings();
|
||||
}
|
||||
|
@ -23,8 +23,8 @@ private:
|
||||
void LoadSettings();
|
||||
void SaveSettings();
|
||||
|
||||
void OnGCTypeChanged(int state);
|
||||
void OnGCPadConfigure();
|
||||
void OnGCTypeChanged(size_t index);
|
||||
void OnGCPadConfigure(size_t index);
|
||||
|
||||
void CreateLayout();
|
||||
void ConnectWidgets();
|
||||
|
@ -33,8 +33,9 @@ AdvancedWidget::AdvancedWidget(GraphicsWindow* parent)
|
||||
AddDescriptions();
|
||||
|
||||
connect(parent, &GraphicsWindow::BackendChanged, this, &AdvancedWidget::OnBackendChanged);
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
|
||||
[=](Core::State state) { OnEmulationStateChanged(state != Core::State::Uninitialized); });
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this](Core::State state) {
|
||||
OnEmulationStateChanged(state != Core::State::Uninitialized);
|
||||
});
|
||||
|
||||
OnBackendChanged();
|
||||
OnEmulationStateChanged(Core::GetState() != Core::State::Uninitialized);
|
||||
|
@ -41,8 +41,9 @@ GeneralWidget::GeneralWidget(X11Utils::XRRConfiguration* xrr_config, GraphicsWin
|
||||
emit BackendChanged(QString::fromStdString(Config::Get(Config::MAIN_GFX_BACKEND)));
|
||||
|
||||
connect(parent, &GraphicsWindow::BackendChanged, this, &GeneralWidget::OnBackendChanged);
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
|
||||
[=](Core::State state) { OnEmulationStateChanged(state != Core::State::Uninitialized); });
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this](Core::State state) {
|
||||
OnEmulationStateChanged(state != Core::State::Uninitialized);
|
||||
});
|
||||
OnEmulationStateChanged(Core::GetState() != Core::State::Uninitialized);
|
||||
}
|
||||
|
||||
|
@ -34,8 +34,9 @@ SoftwareRendererWidget::SoftwareRendererWidget(GraphicsWindow* parent)
|
||||
emit BackendChanged(QString::fromStdString(Config::Get(Config::MAIN_GFX_BACKEND)));
|
||||
|
||||
connect(parent, &GraphicsWindow::BackendChanged, [this] { LoadSettings(); });
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
|
||||
[=](Core::State state) { OnEmulationStateChanged(state != Core::State::Uninitialized); });
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this](Core::State state) {
|
||||
OnEmulationStateChanged(state != Core::State::Uninitialized);
|
||||
});
|
||||
OnEmulationStateChanged(Core::GetState() != Core::State::Uninitialized);
|
||||
}
|
||||
|
||||
|
@ -32,6 +32,7 @@
|
||||
#include "DolphinQt/Config/Mapping/MappingWindow.h"
|
||||
#include "DolphinQt/QtUtils/ModalMessageBox.h"
|
||||
#include "DolphinQt/QtUtils/NonDefaultQPushButton.h"
|
||||
#include "DolphinQt/QtUtils/SignalBlocking.h"
|
||||
#include "DolphinQt/Settings.h"
|
||||
|
||||
#include "UICommon/UICommon.h"
|
||||
@ -39,8 +40,13 @@
|
||||
WiimoteControllersWidget::WiimoteControllersWidget(QWidget* parent) : QWidget(parent)
|
||||
{
|
||||
CreateLayout();
|
||||
LoadSettings();
|
||||
ConnectWidgets();
|
||||
|
||||
connect(&Settings::Instance(), &Settings::ConfigChanged, this,
|
||||
[this] { LoadSettings(Core::GetState()); });
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
|
||||
[this](Core::State state) { LoadSettings(state); });
|
||||
LoadSettings(Core::GetState());
|
||||
}
|
||||
|
||||
static int GetRadioButtonIndicatorWidth()
|
||||
@ -153,20 +159,20 @@ void WiimoteControllersWidget::CreateLayout()
|
||||
|
||||
void WiimoteControllersWidget::ConnectWidgets()
|
||||
{
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
|
||||
&WiimoteControllersWidget::UpdateDisabledWiimoteControls);
|
||||
connect(m_wiimote_passthrough, &QRadioButton::toggled, this, [this] {
|
||||
SaveSettings();
|
||||
LoadSettings(Core::GetState());
|
||||
});
|
||||
connect(m_wiimote_ciface, &QCheckBox::toggled, this, [this] {
|
||||
SaveSettings();
|
||||
LoadSettings(Core::GetState());
|
||||
WiimoteReal::HandleWiimotesInControllerInterfaceSettingChange();
|
||||
});
|
||||
connect(m_wiimote_continuous_scanning, &QCheckBox::toggled, this, [this] {
|
||||
SaveSettings();
|
||||
LoadSettings(Core::GetState());
|
||||
});
|
||||
|
||||
connect(m_wiimote_passthrough, &QRadioButton::toggled, this,
|
||||
&WiimoteControllersWidget::OnWiimoteModeChanged);
|
||||
connect(m_wiimote_ciface, &QCheckBox::toggled, this,
|
||||
&WiimoteControllersWidget::OnWiimoteModeChanged);
|
||||
connect(m_wiimote_ciface, &QCheckBox::toggled, this,
|
||||
&WiimoteReal::HandleWiimotesInControllerInterfaceSettingChange);
|
||||
connect(m_wiimote_continuous_scanning, &QCheckBox::toggled, this,
|
||||
&WiimoteControllersWidget::OnWiimoteModeChanged);
|
||||
|
||||
connect(m_wiimote_continuous_scanning, &QCheckBox::toggled, this,
|
||||
&WiimoteControllersWidget::SaveSettings);
|
||||
connect(m_wiimote_real_balance_board, &QCheckBox::toggled, this,
|
||||
&WiimoteControllersWidget::SaveSettings);
|
||||
connect(m_wiimote_speaker_data, &QCheckBox::toggled, this,
|
||||
@ -180,61 +186,15 @@ void WiimoteControllersWidget::ConnectWidgets()
|
||||
|
||||
for (size_t i = 0; i < m_wiimote_groups.size(); i++)
|
||||
{
|
||||
connect(m_wiimote_boxes[i], qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
&WiimoteControllersWidget::SaveSettings);
|
||||
connect(m_wiimote_boxes[i], qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
&WiimoteControllersWidget::OnWiimoteModeChanged);
|
||||
connect(m_wiimote_boxes[i], qOverload<int>(&QComboBox::currentIndexChanged), this, [this] {
|
||||
SaveSettings();
|
||||
LoadSettings(Core::GetState());
|
||||
});
|
||||
connect(m_wiimote_buttons[i], &QPushButton::clicked, this,
|
||||
&WiimoteControllersWidget::OnWiimoteConfigure);
|
||||
[this, i] { OnWiimoteConfigure(i); });
|
||||
}
|
||||
}
|
||||
|
||||
void WiimoteControllersWidget::OnWiimoteModeChanged()
|
||||
{
|
||||
SaveSettings();
|
||||
|
||||
// Make sure continuous scanning setting is applied.
|
||||
WiimoteReal::Initialize(::Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES);
|
||||
|
||||
UpdateDisabledWiimoteControls();
|
||||
}
|
||||
|
||||
void WiimoteControllersWidget::UpdateDisabledWiimoteControls()
|
||||
{
|
||||
const bool running = Core::GetState() != Core::State::Uninitialized;
|
||||
|
||||
m_wiimote_emu->setEnabled(!running);
|
||||
m_wiimote_passthrough->setEnabled(!running);
|
||||
|
||||
const bool running_gc = running && !SConfig::GetInstance().bWii;
|
||||
const bool enable_passthrough = m_wiimote_passthrough->isChecked() && !running_gc;
|
||||
const bool enable_emu_bt = !m_wiimote_passthrough->isChecked() && !running_gc;
|
||||
|
||||
m_wiimote_sync->setEnabled(enable_passthrough);
|
||||
m_wiimote_reset->setEnabled(enable_passthrough);
|
||||
|
||||
for (auto* pt_label : m_wiimote_pt_labels)
|
||||
pt_label->setEnabled(enable_passthrough);
|
||||
|
||||
for (size_t i = 0; i < m_wiimote_groups.size(); i++)
|
||||
{
|
||||
m_wiimote_labels[i]->setEnabled(enable_emu_bt);
|
||||
m_wiimote_boxes[i]->setEnabled(enable_emu_bt);
|
||||
|
||||
const bool is_emu_wiimote = m_wiimote_boxes[i]->currentIndex() == 1 || m_wiimote_boxes[i]->currentIndex() == 3;
|
||||
m_wiimote_buttons[i]->setEnabled(enable_emu_bt && is_emu_wiimote);
|
||||
}
|
||||
|
||||
m_wiimote_real_balance_board->setEnabled(enable_emu_bt);
|
||||
m_wiimote_speaker_data->setEnabled(enable_emu_bt);
|
||||
|
||||
const bool ciface_wiimotes = m_wiimote_ciface->isChecked();
|
||||
|
||||
m_wiimote_refresh->setEnabled((enable_emu_bt || ciface_wiimotes) &&
|
||||
!m_wiimote_continuous_scanning->isChecked());
|
||||
m_wiimote_continuous_scanning->setEnabled(enable_emu_bt || ciface_wiimotes);
|
||||
}
|
||||
|
||||
void WiimoteControllersWidget::OnBluetoothPassthroughResetPressed()
|
||||
{
|
||||
const auto ios = IOS::HLE::GetIOS();
|
||||
@ -273,15 +233,8 @@ void WiimoteControllersWidget::OnWiimoteRefreshPressed()
|
||||
WiimoteReal::Refresh();
|
||||
}
|
||||
|
||||
void WiimoteControllersWidget::OnWiimoteConfigure()
|
||||
void WiimoteControllersWidget::OnWiimoteConfigure(size_t index)
|
||||
{
|
||||
size_t index;
|
||||
for (index = 0; index < m_wiimote_groups.size(); index++)
|
||||
{
|
||||
if (m_wiimote_buttons[index] == QObject::sender())
|
||||
break;
|
||||
}
|
||||
|
||||
MappingWindow::Type type;
|
||||
switch (m_wiimote_boxes[index]->currentIndex())
|
||||
{
|
||||
@ -320,45 +273,86 @@ void WiimoteControllersWidget::OnWiimoteConfigure()
|
||||
window->show();
|
||||
}
|
||||
|
||||
void WiimoteControllersWidget::LoadSettings()
|
||||
void WiimoteControllersWidget::LoadSettings(Core::State state)
|
||||
{
|
||||
for (size_t i = 0; i < m_wiimote_groups.size(); i++)
|
||||
{
|
||||
m_wiimote_boxes[i]->setCurrentIndex(int(Config::Get(Config::GetInfoForWiimoteSource(int(i)))));
|
||||
SignalBlocking(m_wiimote_boxes[i])
|
||||
->setCurrentIndex(int(Config::Get(Config::GetInfoForWiimoteSource(int(i)))));
|
||||
}
|
||||
m_wiimote_real_balance_board->setChecked(Config::Get(Config::WIIMOTE_BB_SOURCE) ==
|
||||
WiimoteSource::Real);
|
||||
m_wiimote_speaker_data->setChecked(Config::Get(Config::MAIN_WIIMOTE_ENABLE_SPEAKER));
|
||||
m_wiimote_ciface->setChecked(Config::Get(Config::MAIN_CONNECT_WIIMOTES_FOR_CONTROLLER_INTERFACE));
|
||||
m_wiimote_continuous_scanning->setChecked(Config::Get(Config::MAIN_WIIMOTE_CONTINUOUS_SCANNING));
|
||||
SignalBlocking(m_wiimote_real_balance_board)
|
||||
->setChecked(Config::Get(Config::WIIMOTE_BB_SOURCE) == WiimoteSource::Real);
|
||||
SignalBlocking(m_wiimote_speaker_data)
|
||||
->setChecked(Config::Get(Config::MAIN_WIIMOTE_ENABLE_SPEAKER));
|
||||
SignalBlocking(m_wiimote_ciface)
|
||||
->setChecked(Config::Get(Config::MAIN_CONNECT_WIIMOTES_FOR_CONTROLLER_INTERFACE));
|
||||
SignalBlocking(m_wiimote_continuous_scanning)
|
||||
->setChecked(Config::Get(Config::MAIN_WIIMOTE_CONTINUOUS_SCANNING));
|
||||
|
||||
if (Config::Get(Config::MAIN_BLUETOOTH_PASSTHROUGH_ENABLED))
|
||||
m_wiimote_passthrough->setChecked(true);
|
||||
SignalBlocking(m_wiimote_passthrough)->setChecked(true);
|
||||
else
|
||||
m_wiimote_emu->setChecked(true);
|
||||
SignalBlocking(m_wiimote_emu)->setChecked(true);
|
||||
|
||||
OnWiimoteModeChanged();
|
||||
// Make sure continuous scanning setting is applied.
|
||||
WiimoteReal::Initialize(::Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES);
|
||||
|
||||
const bool running = state != Core::State::Uninitialized;
|
||||
|
||||
m_wiimote_emu->setEnabled(!running);
|
||||
m_wiimote_passthrough->setEnabled(!running);
|
||||
|
||||
const bool running_gc = running && !SConfig::GetInstance().bWii;
|
||||
const bool enable_passthrough = m_wiimote_passthrough->isChecked() && !running_gc;
|
||||
const bool enable_emu_bt = !m_wiimote_passthrough->isChecked() && !running_gc;
|
||||
|
||||
m_wiimote_sync->setEnabled(enable_passthrough);
|
||||
m_wiimote_reset->setEnabled(enable_passthrough);
|
||||
|
||||
for (auto* pt_label : m_wiimote_pt_labels)
|
||||
pt_label->setEnabled(enable_passthrough);
|
||||
|
||||
for (size_t i = 0; i < m_wiimote_groups.size(); i++)
|
||||
{
|
||||
m_wiimote_labels[i]->setEnabled(enable_emu_bt);
|
||||
m_wiimote_boxes[i]->setEnabled(enable_emu_bt);
|
||||
|
||||
const bool is_emu_wiimote = m_wiimote_boxes[i]->currentIndex() == 1;
|
||||
m_wiimote_buttons[i]->setEnabled(enable_emu_bt && is_emu_wiimote);
|
||||
}
|
||||
|
||||
m_wiimote_real_balance_board->setEnabled(enable_emu_bt);
|
||||
m_wiimote_speaker_data->setEnabled(enable_emu_bt);
|
||||
|
||||
const bool ciface_wiimotes = m_wiimote_ciface->isChecked();
|
||||
|
||||
m_wiimote_refresh->setEnabled((enable_emu_bt || ciface_wiimotes) &&
|
||||
!m_wiimote_continuous_scanning->isChecked());
|
||||
m_wiimote_continuous_scanning->setEnabled(enable_emu_bt || ciface_wiimotes);
|
||||
}
|
||||
|
||||
void WiimoteControllersWidget::SaveSettings()
|
||||
{
|
||||
Config::SetBaseOrCurrent(Config::MAIN_WIIMOTE_ENABLE_SPEAKER,
|
||||
m_wiimote_speaker_data->isChecked());
|
||||
Config::SetBaseOrCurrent(Config::MAIN_CONNECT_WIIMOTES_FOR_CONTROLLER_INTERFACE,
|
||||
m_wiimote_ciface->isChecked());
|
||||
Config::SetBaseOrCurrent(Config::MAIN_WIIMOTE_CONTINUOUS_SCANNING,
|
||||
m_wiimote_continuous_scanning->isChecked());
|
||||
Config::SetBaseOrCurrent(Config::MAIN_BLUETOOTH_PASSTHROUGH_ENABLED,
|
||||
m_wiimote_passthrough->isChecked());
|
||||
|
||||
const WiimoteSource bb_source =
|
||||
m_wiimote_real_balance_board->isChecked() ? WiimoteSource::Real : WiimoteSource::None;
|
||||
Config::SetBaseOrCurrent(Config::WIIMOTE_BB_SOURCE, bb_source);
|
||||
|
||||
for (size_t i = 0; i < m_wiimote_groups.size(); i++)
|
||||
{
|
||||
const int index = m_wiimote_boxes[i]->currentIndex();
|
||||
Config::SetBaseOrCurrent(Config::GetInfoForWiimoteSource(int(i)), WiimoteSource(index));
|
||||
Config::ConfigChangeCallbackGuard config_guard;
|
||||
Config::SetBaseOrCurrent(Config::MAIN_WIIMOTE_ENABLE_SPEAKER,
|
||||
m_wiimote_speaker_data->isChecked());
|
||||
Config::SetBaseOrCurrent(Config::MAIN_CONNECT_WIIMOTES_FOR_CONTROLLER_INTERFACE,
|
||||
m_wiimote_ciface->isChecked());
|
||||
Config::SetBaseOrCurrent(Config::MAIN_WIIMOTE_CONTINUOUS_SCANNING,
|
||||
m_wiimote_continuous_scanning->isChecked());
|
||||
Config::SetBaseOrCurrent(Config::MAIN_BLUETOOTH_PASSTHROUGH_ENABLED,
|
||||
m_wiimote_passthrough->isChecked());
|
||||
|
||||
const WiimoteSource bb_source =
|
||||
m_wiimote_real_balance_board->isChecked() ? WiimoteSource::Real : WiimoteSource::None;
|
||||
Config::SetBaseOrCurrent(Config::WIIMOTE_BB_SOURCE, bb_source);
|
||||
|
||||
for (size_t i = 0; i < m_wiimote_groups.size(); i++)
|
||||
{
|
||||
const int index = m_wiimote_boxes[i]->currentIndex();
|
||||
Config::SetBaseOrCurrent(Config::GetInfoForWiimoteSource(int(i)), WiimoteSource(index));
|
||||
}
|
||||
}
|
||||
|
||||
SConfig::GetInstance().SaveSettings();
|
||||
|
@ -16,6 +16,11 @@ class QLabel;
|
||||
class QPushButton;
|
||||
class QRadioButton;
|
||||
|
||||
namespace Core
|
||||
{
|
||||
enum class State;
|
||||
}
|
||||
|
||||
class WiimoteControllersWidget final : public QWidget
|
||||
{
|
||||
Q_OBJECT
|
||||
@ -23,17 +28,15 @@ public:
|
||||
explicit WiimoteControllersWidget(QWidget* parent);
|
||||
|
||||
private:
|
||||
void OnWiimoteModeChanged();
|
||||
void UpdateDisabledWiimoteControls();
|
||||
void SaveSettings();
|
||||
void OnBluetoothPassthroughSyncPressed();
|
||||
void OnBluetoothPassthroughResetPressed();
|
||||
void OnWiimoteRefreshPressed();
|
||||
void OnWiimoteConfigure();
|
||||
void OnWiimoteConfigure(size_t index);
|
||||
|
||||
void CreateLayout();
|
||||
void ConnectWidgets();
|
||||
void LoadSettings();
|
||||
void LoadSettings(Core::State state);
|
||||
|
||||
QGroupBox* m_wiimote_box;
|
||||
QGridLayout* m_wiimote_layout;
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <QHBoxLayout>
|
||||
#include <QLabel>
|
||||
#include <QLineEdit>
|
||||
#include <QMenuBar>
|
||||
#include <QPushButton>
|
||||
#include <QRegularExpression>
|
||||
#include <QScrollArea>
|
||||
@ -114,7 +115,6 @@ void MemoryWidget::CreateWidgets()
|
||||
m_data_edit = new QLineEdit;
|
||||
m_base_check = new QCheckBox(tr("Hex"));
|
||||
m_set_value = new QPushButton(tr("Set &Value"));
|
||||
m_from_file = new QPushButton(tr("Set Value From File"));
|
||||
m_data_preview = new QLabel;
|
||||
|
||||
m_base_check->setLayoutDirection(Qt::RightToLeft);
|
||||
@ -140,20 +140,6 @@ void MemoryWidget::CreateWidgets()
|
||||
m_input_combo->addItem(tr("Signed 16"), int(Type::Signed16));
|
||||
m_input_combo->addItem(tr("Signed 32"), int(Type::Signed32));
|
||||
|
||||
// Dump
|
||||
auto* dump_group = new QGroupBox(tr("Dump"));
|
||||
auto* dump_layout = new QVBoxLayout;
|
||||
dump_group->setLayout(dump_layout);
|
||||
m_dump_mram = new QPushButton(tr("Dump &MRAM"));
|
||||
m_dump_exram = new QPushButton(tr("Dump &ExRAM"));
|
||||
m_dump_aram = new QPushButton(tr("Dump &ARAM"));
|
||||
m_dump_fake_vmem = new QPushButton(tr("Dump &FakeVMEM"));
|
||||
|
||||
dump_layout->addWidget(m_dump_mram);
|
||||
dump_layout->addWidget(m_dump_exram);
|
||||
dump_layout->addWidget(m_dump_aram);
|
||||
dump_layout->addWidget(m_dump_fake_vmem);
|
||||
|
||||
// Search Options
|
||||
auto* search_group = new QGroupBox(tr("Search"));
|
||||
auto* search_layout = new QVBoxLayout;
|
||||
@ -253,14 +239,31 @@ void MemoryWidget::CreateWidgets()
|
||||
// Sidebar
|
||||
auto* sidebar = new QWidget;
|
||||
auto* sidebar_layout = new QVBoxLayout;
|
||||
|
||||
// Sidebar top menu
|
||||
QMenuBar* menubar = new QMenuBar(sidebar);
|
||||
menubar->setNativeMenuBar(false);
|
||||
QMenu* menu_actions = new QMenu(tr("&Actions"));
|
||||
|
||||
menu_actions->addAction(tr("&Load file to current address"), this,
|
||||
&MemoryWidget::OnSetValueFromFile);
|
||||
menu_actions->addSeparator();
|
||||
menu_actions->addAction(tr("Dump &MRAM"), this, &MemoryWidget::OnDumpMRAM);
|
||||
menu_actions->addAction(tr("Dump &ExRAM"), this, &MemoryWidget::OnDumpExRAM);
|
||||
menu_actions->addAction(tr("Dump &ARAM"), this, &MemoryWidget::OnDumpARAM);
|
||||
menu_actions->addAction(tr("Dump &FakeVMEM"), this, &MemoryWidget::OnDumpFakeVMEM);
|
||||
|
||||
menubar->addMenu(menu_actions);
|
||||
|
||||
sidebar_layout->setSpacing(1);
|
||||
sidebar->setLayout(sidebar_layout);
|
||||
sidebar_layout->addItem(new QSpacerItem(1, 20));
|
||||
sidebar_layout->addWidget(m_address_splitter);
|
||||
sidebar_layout->addLayout(input_layout);
|
||||
sidebar_layout->addWidget(m_input_combo);
|
||||
sidebar_layout->addItem(new QSpacerItem(1, 10));
|
||||
sidebar_layout->addWidget(m_data_preview);
|
||||
sidebar_layout->addWidget(m_set_value);
|
||||
sidebar_layout->addWidget(m_from_file);
|
||||
sidebar_layout->addItem(new QSpacerItem(1, 10));
|
||||
sidebar_layout->addWidget(search_group);
|
||||
sidebar_layout->addItem(new QSpacerItem(1, 10));
|
||||
@ -269,8 +272,6 @@ void MemoryWidget::CreateWidgets()
|
||||
sidebar_layout->addWidget(address_space_group);
|
||||
sidebar_layout->addItem(new QSpacerItem(1, 10));
|
||||
sidebar_layout->addWidget(bp_group);
|
||||
sidebar_layout->addItem(new QSpacerItem(1, 10));
|
||||
sidebar_layout->addWidget(dump_group);
|
||||
sidebar_layout->addItem(new QSpacerItem(0, 0, QSizePolicy::Expanding, QSizePolicy::Expanding));
|
||||
|
||||
// Splitter
|
||||
@ -302,14 +303,7 @@ void MemoryWidget::ConnectWidgets()
|
||||
|
||||
connect(m_input_combo, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
&MemoryWidget::ValidateAndPreviewInputValue);
|
||||
|
||||
connect(m_set_value, &QPushButton::clicked, this, &MemoryWidget::OnSetValue);
|
||||
connect(m_from_file, &QPushButton::clicked, this, &MemoryWidget::OnSetValueFromFile);
|
||||
|
||||
connect(m_dump_mram, &QPushButton::clicked, this, &MemoryWidget::OnDumpMRAM);
|
||||
connect(m_dump_exram, &QPushButton::clicked, this, &MemoryWidget::OnDumpExRAM);
|
||||
connect(m_dump_aram, &QPushButton::clicked, this, &MemoryWidget::OnDumpARAM);
|
||||
connect(m_dump_fake_vmem, &QPushButton::clicked, this, &MemoryWidget::OnDumpFakeVMEM);
|
||||
|
||||
connect(m_find_next, &QPushButton::clicked, this, &MemoryWidget::OnFindNextValue);
|
||||
connect(m_find_previous, &QPushButton::clicked, this, &MemoryWidget::OnFindPreviousValue);
|
||||
|
@ -85,11 +85,6 @@ private:
|
||||
QComboBox* m_row_length_combo;
|
||||
QCheckBox* m_dual_check;
|
||||
QPushButton* m_set_value;
|
||||
QPushButton* m_from_file;
|
||||
QPushButton* m_dump_mram;
|
||||
QPushButton* m_dump_exram;
|
||||
QPushButton* m_dump_aram;
|
||||
QPushButton* m_dump_fake_vmem;
|
||||
|
||||
// Search
|
||||
QPushButton* m_find_next;
|
||||
|
@ -316,6 +316,11 @@ public:
|
||||
|
||||
OPCODE_CALLBACK(CPState& GetCPState()) { return m_cpmem; }
|
||||
|
||||
OPCODE_CALLBACK(u32 GetVertexSize(u8 vat))
|
||||
{
|
||||
return VertexLoaderBase::GetVertexSize(GetCPState().vtx_desc, GetCPState().vtx_attr[vat]);
|
||||
}
|
||||
|
||||
QString text;
|
||||
CPState m_cpmem;
|
||||
};
|
||||
@ -731,6 +736,11 @@ public:
|
||||
|
||||
OPCODE_CALLBACK(CPState& GetCPState()) { return m_cpmem; }
|
||||
|
||||
OPCODE_CALLBACK(u32 GetVertexSize(u8 vat))
|
||||
{
|
||||
return VertexLoaderBase::GetVertexSize(GetCPState().vtx_desc, GetCPState().vtx_attr[vat]);
|
||||
}
|
||||
|
||||
QString text;
|
||||
CPState m_cpmem;
|
||||
};
|
||||
|
@ -358,7 +358,7 @@ void MainWindow::ShutdownControllers()
|
||||
|
||||
void MainWindow::InitCoreCallbacks()
|
||||
{
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [=](Core::State state) {
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this](Core::State state) {
|
||||
if (state == Core::State::Uninitialized)
|
||||
OnStopComplete();
|
||||
if (state != Core::State::Uninitialized && NetPlay::IsNetPlayRunning() && m_controllers_window)
|
||||
@ -375,7 +375,7 @@ void MainWindow::InitCoreCallbacks()
|
||||
|
||||
// Handle file open events
|
||||
auto* filter = new FileOpenEventFilter(QGuiApplication::instance());
|
||||
connect(filter, &FileOpenEventFilter::fileOpened, this, [=](const QString& file_name) {
|
||||
connect(filter, &FileOpenEventFilter::fileOpened, this, [this](const QString& file_name) {
|
||||
StartGame(BootParameters::GenerateFromFile(file_name.toStdString()));
|
||||
});
|
||||
}
|
||||
|
@ -90,7 +90,7 @@ MenuBar::MenuBar(QWidget* parent) : QMenuBar(parent)
|
||||
AddPrimeHackMenu();
|
||||
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
|
||||
[=](Core::State state) { OnEmulationStateChanged(state); });
|
||||
[=, this](Core::State state) { OnEmulationStateChanged(state); });
|
||||
connect(Host::GetInstance(), &Host::UpdateDisasmDialog, this,
|
||||
[this] { OnEmulationStateChanged(Core::GetState()); });
|
||||
|
||||
@ -343,7 +343,7 @@ void MenuBar::AddStateLoadMenu(QMenu* emu_menu)
|
||||
{
|
||||
QAction* action = m_state_load_slots_menu->addAction(QString{});
|
||||
|
||||
connect(action, &QAction::triggered, this, [=]() { emit StateLoadSlotAt(i); });
|
||||
connect(action, &QAction::triggered, this, [=, this]() { emit StateLoadSlotAt(i); });
|
||||
}
|
||||
}
|
||||
|
||||
@ -360,7 +360,7 @@ void MenuBar::AddStateSaveMenu(QMenu* emu_menu)
|
||||
{
|
||||
QAction* action = m_state_save_slots_menu->addAction(QString{});
|
||||
|
||||
connect(action, &QAction::triggered, this, [=]() { emit StateSaveSlotAt(i); });
|
||||
connect(action, &QAction::triggered, this, [=, this]() { emit StateSaveSlotAt(i); });
|
||||
}
|
||||
}
|
||||
|
||||
@ -377,7 +377,7 @@ void MenuBar::AddStateSlotMenu(QMenu* emu_menu)
|
||||
if (Settings::Instance().GetStateSlot() == i)
|
||||
action->setChecked(true);
|
||||
|
||||
connect(action, &QAction::triggered, this, [=]() { emit SetStateSlot(i); });
|
||||
connect(action, &QAction::triggered, this, [=, this]() { emit SetStateSlot(i); });
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -369,7 +369,7 @@ void NetPlayDialog::ConnectWidgets()
|
||||
}
|
||||
});
|
||||
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [=](Core::State state) {
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this](Core::State state) {
|
||||
if (isVisible())
|
||||
{
|
||||
GameStatusChanged(state != Core::State::Uninitialized);
|
||||
@ -850,8 +850,7 @@ void NetPlayDialog::OnMsgStartGame()
|
||||
g_netplay_chat_ui =
|
||||
std::make_unique<NetPlayChatUI>([this](const std::string& message) { SendMessage(message); });
|
||||
|
||||
if (m_host_input_authority &&
|
||||
Settings::Instance().GetNetPlayClient()->GetNetSettings().m_GolfMode)
|
||||
if (m_host_input_authority && Settings::Instance().GetNetPlayClient()->GetNetSettings().golf_mode)
|
||||
{
|
||||
g_netplay_golf_ui = std::make_unique<NetPlayGolfUI>(Settings::Instance().GetNetPlayClient());
|
||||
}
|
||||
|
@ -35,8 +35,9 @@ AudioPane::AudioPane()
|
||||
ConnectWidgets();
|
||||
|
||||
connect(&Settings::Instance(), &Settings::VolumeChanged, this, &AudioPane::OnVolumeChanged);
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
|
||||
[=](Core::State state) { OnEmulationStateChanged(state != Core::State::Uninitialized); });
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this](Core::State state) {
|
||||
OnEmulationStateChanged(state != Core::State::Uninitialized);
|
||||
});
|
||||
|
||||
OnEmulationStateChanged(Core::GetState() != Core::State::Uninitialized);
|
||||
}
|
||||
|
@ -213,8 +213,9 @@ void InterfacePane::ConnectLayout()
|
||||
connect(m_checkbox_disable_screensaver, &QCheckBox::toggled, this, &InterfacePane::OnSaveConfig);
|
||||
connect(m_checkbox_show_debugging_ui, &QCheckBox::toggled, this, &InterfacePane::OnSaveConfig);
|
||||
connect(m_checkbox_focused_hotkeys, &QCheckBox::toggled, this, &InterfacePane::OnSaveConfig);
|
||||
connect(m_combobox_theme, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
[=](int index) { Settings::Instance().SetThemeName(m_combobox_theme->itemText(index)); });
|
||||
connect(
|
||||
m_combobox_theme, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
[this](int index) { Settings::Instance().SetThemeName(m_combobox_theme->itemText(index)); });
|
||||
connect(m_combobox_userstyle, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
&InterfacePane::OnSaveConfig);
|
||||
connect(m_combobox_language, qOverload<int>(&QComboBox::currentIndexChanged), this,
|
||||
|
@ -196,7 +196,7 @@ QGridLayout* PathPane::MakePathsLayout()
|
||||
|
||||
m_dump_edit = new QLineEdit(QString::fromStdString(File::GetUserPath(D_DUMP_IDX)));
|
||||
connect(m_dump_edit, &QLineEdit::editingFinished,
|
||||
[=] { Config::SetBase(Config::MAIN_DUMP_PATH, m_dump_edit->text().toStdString()); });
|
||||
[this] { Config::SetBase(Config::MAIN_DUMP_PATH, m_dump_edit->text().toStdString()); });
|
||||
QPushButton* dump_open = new NonDefaultQPushButton(QStringLiteral("..."));
|
||||
connect(dump_open, &QPushButton::clicked, this, &PathPane::BrowseDump);
|
||||
layout->addWidget(new QLabel(tr("Dump Path:")), 2, 0);
|
||||
@ -205,7 +205,7 @@ QGridLayout* PathPane::MakePathsLayout()
|
||||
|
||||
m_load_edit = new QLineEdit(QString::fromStdString(File::GetUserPath(D_LOAD_IDX)));
|
||||
connect(m_load_edit, &QLineEdit::editingFinished,
|
||||
[=] { Config::SetBase(Config::MAIN_LOAD_PATH, m_load_edit->text().toStdString()); });
|
||||
[this] { Config::SetBase(Config::MAIN_LOAD_PATH, m_load_edit->text().toStdString()); });
|
||||
QPushButton* load_open = new NonDefaultQPushButton(QStringLiteral("..."));
|
||||
connect(load_open, &QPushButton::clicked, this, &PathPane::BrowseLoad);
|
||||
layout->addWidget(new QLabel(tr("Load Path:")), 3, 0);
|
||||
@ -214,7 +214,7 @@ QGridLayout* PathPane::MakePathsLayout()
|
||||
|
||||
m_resource_pack_edit =
|
||||
new QLineEdit(QString::fromStdString(File::GetUserPath(D_RESOURCEPACK_IDX)));
|
||||
connect(m_resource_pack_edit, &QLineEdit::editingFinished, [=] {
|
||||
connect(m_resource_pack_edit, &QLineEdit::editingFinished, [this] {
|
||||
Config::SetBase(Config::MAIN_RESOURCEPACK_PATH, m_resource_pack_edit->text().toStdString());
|
||||
});
|
||||
QPushButton* resource_pack_open = new NonDefaultQPushButton(QStringLiteral("..."));
|
||||
@ -225,7 +225,7 @@ QGridLayout* PathPane::MakePathsLayout()
|
||||
|
||||
m_wfs_edit = new QLineEdit(QString::fromStdString(File::GetUserPath(D_WFSROOT_IDX)));
|
||||
connect(m_load_edit, &QLineEdit::editingFinished,
|
||||
[=] { Config::SetBase(Config::MAIN_WFS_PATH, m_wfs_edit->text().toStdString()); });
|
||||
[this] { Config::SetBase(Config::MAIN_WFS_PATH, m_wfs_edit->text().toStdString()); });
|
||||
QPushButton* wfs_open = new NonDefaultQPushButton(QStringLiteral("..."));
|
||||
connect(wfs_open, &QPushButton::clicked, this, &PathPane::BrowseWFS);
|
||||
layout->addWidget(new QLabel(tr("WFS Path:")), 5, 0);
|
||||
|
@ -107,8 +107,9 @@ void WiiPane::ConnectLayout()
|
||||
connect(m_wiimote_motor, &QCheckBox::toggled, this, &WiiPane::OnSaveConfig);
|
||||
|
||||
// Emulation State
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this,
|
||||
[=](Core::State state) { OnEmulationStateChanged(state != Core::State::Uninitialized); });
|
||||
connect(&Settings::Instance(), &Settings::EmulationStateChanged, this, [this](Core::State state) {
|
||||
OnEmulationStateChanged(state != Core::State::Uninitialized);
|
||||
});
|
||||
}
|
||||
|
||||
void WiiPane::CreateMisc()
|
||||
|
@ -103,13 +103,15 @@ struct ThreePointCalibration
|
||||
template <typename T, size_t Bits>
|
||||
struct RawValue
|
||||
{
|
||||
RawValue() = default;
|
||||
explicit RawValue(const T& value_) : value{value_} {}
|
||||
constexpr RawValue() = default;
|
||||
constexpr explicit RawValue(const T& value_) : value{value_} {}
|
||||
|
||||
static constexpr size_t BITS_OF_PRECISION = Bits;
|
||||
|
||||
T value;
|
||||
|
||||
constexpr bool operator==(const RawValue& other) const = default;
|
||||
|
||||
template <typename OtherT, size_t OtherBits>
|
||||
auto GetNormalizedValue(const TwoPointCalibration<OtherT, OtherBits>& calibration) const
|
||||
{
|
||||
@ -206,9 +208,9 @@ public:
|
||||
static_assert(std::is_integral<T>(), "T is only sane for int types.");
|
||||
static_assert(std::is_floating_point<F>(), "F is only sane for float types.");
|
||||
|
||||
static_assert(std::numeric_limits<long>::min() <= std::numeric_limits<T>::min() &&
|
||||
std::numeric_limits<long>::max() >= std::numeric_limits<T>::max(),
|
||||
"long is not a superset of T. use of std::lround is not sane.");
|
||||
static_assert(std::numeric_limits<long long>::min() <= std::numeric_limits<T>::min() &&
|
||||
std::numeric_limits<long long>::max() >= std::numeric_limits<T>::max(),
|
||||
"long long is not a superset of T. use of std::llround is not sane.");
|
||||
|
||||
// Here we round when converting from float to int.
|
||||
// After applying our deadzone, resizing, and reshaping math
|
||||
@ -216,9 +218,9 @@ public:
|
||||
// Casting would round down but rounding will yield our "zero_value".
|
||||
|
||||
if (input_value > 0)
|
||||
return T(std::lround((pos_1_value - zero_value) * input_value + zero_value));
|
||||
return T(std::llround((pos_1_value - zero_value) * input_value + zero_value));
|
||||
else
|
||||
return T(std::lround((zero_value - neg_1_value) * input_value + zero_value));
|
||||
return T(std::llround((zero_value - neg_1_value) * input_value + zero_value));
|
||||
}
|
||||
|
||||
protected:
|
||||
|
@ -4,6 +4,7 @@
|
||||
#include "UpdaterCommon/UpdaterCommon.h"
|
||||
|
||||
#include <array>
|
||||
#include <memory>
|
||||
#include <optional>
|
||||
|
||||
#include <OptionParser.h>
|
||||
@ -132,16 +133,17 @@ std::optional<std::string> GzipInflate(const std::string& data)
|
||||
inflateInit2(&zstrm, 16 + MAX_WBITS);
|
||||
|
||||
std::string out;
|
||||
char buffer[4096];
|
||||
const size_t buf_len = 20 * 1024 * 1024;
|
||||
auto buffer = std::make_unique<char[]>(buf_len);
|
||||
int ret;
|
||||
|
||||
do
|
||||
{
|
||||
zstrm.avail_out = sizeof(buffer);
|
||||
zstrm.next_out = reinterpret_cast<u8*>(buffer);
|
||||
zstrm.avail_out = buf_len;
|
||||
zstrm.next_out = reinterpret_cast<u8*>(buffer.get());
|
||||
|
||||
ret = inflate(&zstrm, 0);
|
||||
out.append(buffer, sizeof(buffer) - zstrm.avail_out);
|
||||
out.append(buffer.get(), buf_len - zstrm.avail_out);
|
||||
} while (ret == Z_OK);
|
||||
|
||||
inflateEnd(&zstrm);
|
||||
|
@ -112,6 +112,7 @@ void VideoBackend::FillBackendInfo()
|
||||
g_Config.backend_info.bSupportsLogicOp = D3D::SupportsLogicOp(g_Config.iAdapter);
|
||||
g_Config.backend_info.bSupportsSettingObjectNames = true;
|
||||
g_Config.backend_info.bSupportsPartialMultisampleResolve = true;
|
||||
g_Config.backend_info.bSupportsDynamicVertexLoader = false;
|
||||
|
||||
g_Config.backend_info.Adapters = D3DCommon::GetAdapterNames();
|
||||
g_Config.backend_info.AAModes = D3D::GetAAModes(g_Config.iAdapter);
|
||||
|
@ -180,7 +180,8 @@ void Renderer::SetPipeline(const AbstractPipeline* pipeline)
|
||||
m_state.root_signature = dx_pipeline->GetRootSignature();
|
||||
m_dirty_bits |= DirtyState_RootSignature | DirtyState_PS_CBV | DirtyState_VS_CBV |
|
||||
DirtyState_GS_CBV | DirtyState_SRV_Descriptor |
|
||||
DirtyState_Sampler_Descriptor | DirtyState_UAV_Descriptor;
|
||||
DirtyState_Sampler_Descriptor | DirtyState_UAV_Descriptor |
|
||||
DirtyState_VS_SRV_Descriptor;
|
||||
}
|
||||
if (dx_pipeline->UseIntegerRTV() != m_state.using_integer_rtv)
|
||||
{
|
||||
@ -362,6 +363,11 @@ void Renderer::DrawIndexed(u32 base_index, u32 num_indices, u32 base_vertex)
|
||||
if (!ApplyState())
|
||||
return;
|
||||
|
||||
// DX12 is great and doesn't include the base vertex in SV_VertexID
|
||||
if (static_cast<const DXPipeline*>(m_current_pipeline)->GetUsage() ==
|
||||
AbstractPipelineUsage::GXUber)
|
||||
g_dx_context->GetCommandList()->SetGraphicsRoot32BitConstant(
|
||||
ROOT_PARAMETER_BASE_VERTEX_CONSTANT, base_vertex, 0);
|
||||
g_dx_context->GetCommandList()->DrawIndexedInstanced(num_indices, 1, base_index, base_vertex, 0);
|
||||
}
|
||||
|
||||
@ -494,18 +500,22 @@ void Renderer::SetPixelShaderUAV(D3D12_CPU_DESCRIPTOR_HANDLE handle)
|
||||
m_dirty_bits |= DirtyState_PS_UAV;
|
||||
}
|
||||
|
||||
void Renderer::SetVertexBuffer(D3D12_GPU_VIRTUAL_ADDRESS address, u32 stride, u32 size)
|
||||
void Renderer::SetVertexBuffer(D3D12_GPU_VIRTUAL_ADDRESS address, D3D12_CPU_DESCRIPTOR_HANDLE srv,
|
||||
u32 stride, u32 size)
|
||||
{
|
||||
if (m_state.vertex_buffer.BufferLocation == address &&
|
||||
m_state.vertex_buffer.StrideInBytes == stride && m_state.vertex_buffer.SizeInBytes == size)
|
||||
if (m_state.vertex_buffer.BufferLocation != address ||
|
||||
m_state.vertex_buffer.StrideInBytes != stride || m_state.vertex_buffer.SizeInBytes != size)
|
||||
{
|
||||
return;
|
||||
m_state.vertex_buffer.BufferLocation = address;
|
||||
m_state.vertex_buffer.StrideInBytes = stride;
|
||||
m_state.vertex_buffer.SizeInBytes = size;
|
||||
m_dirty_bits |= DirtyState_VertexBuffer;
|
||||
}
|
||||
if (m_state.vs_srv.ptr != srv.ptr)
|
||||
{
|
||||
m_state.vs_srv = srv;
|
||||
m_dirty_bits |= DirtyState_VS_SRV;
|
||||
}
|
||||
|
||||
m_state.vertex_buffer.BufferLocation = address;
|
||||
m_state.vertex_buffer.StrideInBytes = stride;
|
||||
m_state.vertex_buffer.SizeInBytes = size;
|
||||
m_dirty_bits |= DirtyState_VertexBuffer;
|
||||
}
|
||||
|
||||
void Renderer::SetIndexBuffer(D3D12_GPU_VIRTUAL_ADDRESS address, u32 size, DXGI_FORMAT format)
|
||||
@ -535,15 +545,17 @@ bool Renderer::ApplyState()
|
||||
// Clear bits before actually changing state. Some state (e.g. cbuffers) can't be set
|
||||
// if utility pipelines are bound.
|
||||
const u32 dirty_bits = m_dirty_bits;
|
||||
m_dirty_bits &= ~(
|
||||
DirtyState_Framebuffer | DirtyState_Pipeline | DirtyState_Viewport | DirtyState_ScissorRect |
|
||||
DirtyState_PS_UAV | DirtyState_PS_CBV | DirtyState_VS_CBV | DirtyState_GS_CBV |
|
||||
DirtyState_SRV_Descriptor | DirtyState_Sampler_Descriptor | DirtyState_UAV_Descriptor |
|
||||
DirtyState_VertexBuffer | DirtyState_IndexBuffer | DirtyState_PrimitiveTopology);
|
||||
m_dirty_bits &=
|
||||
~(DirtyState_Framebuffer | DirtyState_Pipeline | DirtyState_Viewport |
|
||||
DirtyState_ScissorRect | DirtyState_PS_UAV | DirtyState_PS_CBV | DirtyState_VS_CBV |
|
||||
DirtyState_GS_CBV | DirtyState_SRV_Descriptor | DirtyState_Sampler_Descriptor |
|
||||
DirtyState_UAV_Descriptor | DirtyState_VertexBuffer | DirtyState_IndexBuffer |
|
||||
DirtyState_PrimitiveTopology | DirtyState_VS_SRV_Descriptor);
|
||||
|
||||
auto* const cmdlist = g_dx_context->GetCommandList();
|
||||
auto* const pipeline = static_cast<const DXPipeline*>(m_current_pipeline);
|
||||
if (dirty_bits & DirtyState_Pipeline)
|
||||
cmdlist->SetPipelineState(static_cast<const DXPipeline*>(m_current_pipeline)->GetPipeline());
|
||||
cmdlist->SetPipelineState(pipeline->GetPipeline());
|
||||
|
||||
if (dirty_bits & DirtyState_Framebuffer)
|
||||
BindFramebuffer(static_cast<DXFramebuffer*>(m_current_framebuffer));
|
||||
@ -572,7 +584,7 @@ bool Renderer::ApplyState()
|
||||
m_state.sampler_descriptor_base);
|
||||
}
|
||||
|
||||
if (static_cast<const DXPipeline*>(m_current_pipeline)->GetUsage() == AbstractPipelineUsage::GX)
|
||||
if (pipeline->GetUsage() != AbstractPipelineUsage::Utility)
|
||||
{
|
||||
if (dirty_bits & DirtyState_VS_CBV)
|
||||
{
|
||||
@ -589,6 +601,13 @@ bool Renderer::ApplyState()
|
||||
}
|
||||
}
|
||||
|
||||
if (dirty_bits & DirtyState_VS_SRV_Descriptor &&
|
||||
pipeline->GetUsage() == AbstractPipelineUsage::GXUber)
|
||||
{
|
||||
cmdlist->SetGraphicsRootDescriptorTable(ROOT_PARAMETER_VS_SRV,
|
||||
m_state.vertex_srv_descriptor_base);
|
||||
}
|
||||
|
||||
if (dirty_bits & DirtyState_GS_CBV)
|
||||
{
|
||||
cmdlist->SetGraphicsRootConstantBufferView(ROOT_PARAMETER_GS_CBV,
|
||||
@ -641,7 +660,9 @@ void Renderer::UpdateDescriptorTables()
|
||||
const bool sampler_update_failed =
|
||||
(m_dirty_bits & DirtyState_Samplers) && !UpdateSamplerDescriptorTable();
|
||||
const bool uav_update_failed = (m_dirty_bits & DirtyState_PS_UAV) && !UpdateUAVDescriptorTable();
|
||||
if (texture_update_failed || sampler_update_failed || uav_update_failed)
|
||||
const bool srv_update_failed =
|
||||
(m_dirty_bits & DirtyState_VS_SRV) && !UpdateVSSRVDescriptorTable();
|
||||
if (texture_update_failed || sampler_update_failed || uav_update_failed || srv_update_failed)
|
||||
{
|
||||
WARN_LOG_FMT(VIDEO, "Executing command list while waiting for temporary {}",
|
||||
texture_update_failed ? "descriptors" : "samplers");
|
||||
@ -651,6 +672,7 @@ void Renderer::UpdateDescriptorTables()
|
||||
UpdateSRVDescriptorTable();
|
||||
UpdateSamplerDescriptorTable();
|
||||
UpdateUAVDescriptorTable();
|
||||
UpdateVSSRVDescriptorTable();
|
||||
}
|
||||
}
|
||||
|
||||
@ -700,6 +722,26 @@ bool Renderer::UpdateUAVDescriptorTable()
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Renderer::UpdateVSSRVDescriptorTable()
|
||||
{
|
||||
if (!g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader ||
|
||||
static_cast<const DXPipeline*>(m_current_pipeline)->GetUsage() !=
|
||||
AbstractPipelineUsage::GXUber)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
DescriptorHandle handle;
|
||||
if (!g_dx_context->GetDescriptorAllocator()->Allocate(1, &handle))
|
||||
return false;
|
||||
|
||||
g_dx_context->GetDevice()->CopyDescriptorsSimple(1, handle.cpu_handle, m_state.vs_srv,
|
||||
D3D12_DESCRIPTOR_HEAP_TYPE_CBV_SRV_UAV);
|
||||
m_state.vertex_srv_descriptor_base = handle.gpu_handle;
|
||||
m_dirty_bits = (m_dirty_bits & ~DirtyState_VS_SRV) | DirtyState_VS_SRV_Descriptor;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Renderer::UpdateComputeUAVDescriptorTable()
|
||||
{
|
||||
DescriptorHandle handle;
|
||||
|
@ -88,7 +88,8 @@ public:
|
||||
void SetPixelShaderUAV(D3D12_CPU_DESCRIPTOR_HANDLE handle);
|
||||
|
||||
// Graphics vertex/index buffer binding.
|
||||
void SetVertexBuffer(D3D12_GPU_VIRTUAL_ADDRESS address, u32 stride, u32 size);
|
||||
void SetVertexBuffer(D3D12_GPU_VIRTUAL_ADDRESS address, D3D12_CPU_DESCRIPTOR_HANDLE srv,
|
||||
u32 stride, u32 size);
|
||||
void SetIndexBuffer(D3D12_GPU_VIRTUAL_ADDRESS address, u32 size, DXGI_FORMAT format);
|
||||
|
||||
// Binds all dirty state
|
||||
@ -126,6 +127,8 @@ private:
|
||||
DirtyState_RootSignature = (1 << 17),
|
||||
DirtyState_ComputeRootSignature = (1 << 18),
|
||||
DirtyState_DescriptorHeaps = (1 << 19),
|
||||
DirtyState_VS_SRV = (1 << 20),
|
||||
DirtyState_VS_SRV_Descriptor = (1 << 21),
|
||||
|
||||
DirtyState_All =
|
||||
DirtyState_Framebuffer | DirtyState_Pipeline | DirtyState_Textures | DirtyState_Samplers |
|
||||
@ -133,7 +136,8 @@ private:
|
||||
DirtyState_PS_UAV | DirtyState_PS_CBV | DirtyState_VS_CBV | DirtyState_GS_CBV |
|
||||
DirtyState_SRV_Descriptor | DirtyState_Sampler_Descriptor | DirtyState_UAV_Descriptor |
|
||||
DirtyState_VertexBuffer | DirtyState_IndexBuffer | DirtyState_PrimitiveTopology |
|
||||
DirtyState_RootSignature | DirtyState_ComputeRootSignature | DirtyState_DescriptorHeaps
|
||||
DirtyState_RootSignature | DirtyState_ComputeRootSignature | DirtyState_DescriptorHeaps |
|
||||
DirtyState_VS_SRV | DirtyState_VS_SRV_Descriptor
|
||||
};
|
||||
|
||||
void CheckForSwapChainChanges();
|
||||
@ -144,6 +148,7 @@ private:
|
||||
void UpdateDescriptorTables();
|
||||
bool UpdateSRVDescriptorTable();
|
||||
bool UpdateUAVDescriptorTable();
|
||||
bool UpdateVSSRVDescriptorTable();
|
||||
bool UpdateComputeUAVDescriptorTable();
|
||||
bool UpdateSamplerDescriptorTable();
|
||||
|
||||
@ -157,11 +162,13 @@ private:
|
||||
DXShader* compute_shader = nullptr;
|
||||
std::array<D3D12_GPU_VIRTUAL_ADDRESS, 3> constant_buffers = {};
|
||||
std::array<D3D12_CPU_DESCRIPTOR_HANDLE, MAX_TEXTURES> textures = {};
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE vs_srv = {};
|
||||
D3D12_CPU_DESCRIPTOR_HANDLE ps_uav = {};
|
||||
SamplerStateSet samplers = {};
|
||||
const DXTexture* compute_image_texture = nullptr;
|
||||
D3D12_VIEWPORT viewport = {};
|
||||
D3D12_RECT scissor = {};
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE vertex_srv_descriptor_base = {};
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE srv_descriptor_base = {};
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE sampler_descriptor_base = {};
|
||||
D3D12_GPU_DESCRIPTOR_HANDLE uav_descriptor_base = {};
|
||||
|
@ -64,6 +64,18 @@ bool VertexManager::Initialize()
|
||||
&srv_desc, dh.cpu_handle);
|
||||
}
|
||||
|
||||
if (!g_dx_context->GetDescriptorHeapManager().Allocate(&m_vertex_srv))
|
||||
{
|
||||
PanicAlertFmt("Failed to allocate descriptor for vertex srv");
|
||||
return false;
|
||||
}
|
||||
|
||||
D3D12_SHADER_RESOURCE_VIEW_DESC srv_desc = {DXGI_FORMAT_R32_UINT, D3D12_SRV_DIMENSION_BUFFER,
|
||||
D3D12_DEFAULT_SHADER_4_COMPONENT_MAPPING};
|
||||
srv_desc.Buffer.NumElements = m_vertex_stream_buffer.GetSize() / sizeof(u32);
|
||||
g_dx_context->GetDevice()->CreateShaderResourceView(m_vertex_stream_buffer.GetBuffer(), &srv_desc,
|
||||
m_vertex_srv.cpu_handle);
|
||||
|
||||
UploadAllConstants();
|
||||
return true;
|
||||
}
|
||||
@ -115,7 +127,8 @@ void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_in
|
||||
ADDSTAT(g_stats.this_frame.bytes_vertex_streamed, static_cast<int>(vertex_data_size));
|
||||
ADDSTAT(g_stats.this_frame.bytes_index_streamed, static_cast<int>(index_data_size));
|
||||
|
||||
Renderer::GetInstance()->SetVertexBuffer(m_vertex_stream_buffer.GetGPUPointer(), vertex_stride,
|
||||
Renderer::GetInstance()->SetVertexBuffer(m_vertex_stream_buffer.GetGPUPointer(),
|
||||
m_vertex_srv.cpu_handle, vertex_stride,
|
||||
m_vertex_stream_buffer.GetSize());
|
||||
Renderer::GetInstance()->SetIndexBuffer(m_index_stream_buffer.GetGPUPointer(),
|
||||
m_index_stream_buffer.GetSize(), DXGI_FORMAT_R16_UINT);
|
||||
|
@ -46,6 +46,7 @@ protected:
|
||||
StreamBuffer m_uniform_stream_buffer;
|
||||
StreamBuffer m_texel_stream_buffer;
|
||||
std::array<DescriptorHandle, NUM_TEXEL_BUFFER_FORMATS> m_texel_buffer_views = {};
|
||||
DescriptorHandle m_vertex_srv = {};
|
||||
};
|
||||
|
||||
} // namespace DX12
|
||||
|
@ -261,6 +261,16 @@ bool DXContext::CreateDescriptorHeaps()
|
||||
return true;
|
||||
}
|
||||
|
||||
static void SetRootParamConstant(D3D12_ROOT_PARAMETER* rp, u32 shader_reg, u32 num_values,
|
||||
D3D12_SHADER_VISIBILITY visibility)
|
||||
{
|
||||
rp->ParameterType = D3D12_ROOT_PARAMETER_TYPE_32BIT_CONSTANTS;
|
||||
rp->Constants.Num32BitValues = num_values;
|
||||
rp->Constants.ShaderRegister = shader_reg;
|
||||
rp->Constants.RegisterSpace = 0;
|
||||
rp->ShaderVisibility = visibility;
|
||||
}
|
||||
|
||||
static void SetRootParamCBV(D3D12_ROOT_PARAMETER* rp, u32 shader_reg,
|
||||
D3D12_SHADER_VISIBILITY visibility)
|
||||
{
|
||||
@ -345,6 +355,11 @@ bool DXContext::CreateGXRootSignature()
|
||||
param_count++;
|
||||
SetRootParamCBV(¶ms[param_count], 0, D3D12_SHADER_VISIBILITY_GEOMETRY);
|
||||
param_count++;
|
||||
SetRootParamTable(¶ms[param_count], &ranges[param_count], D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 3,
|
||||
1, D3D12_SHADER_VISIBILITY_VERTEX);
|
||||
param_count++;
|
||||
SetRootParamConstant(¶ms[param_count], 2, 1, D3D12_SHADER_VISIBILITY_VERTEX);
|
||||
param_count++;
|
||||
|
||||
// Since these must be contiguous, pixel lighting goes to bbox if not enabled.
|
||||
if (g_ActiveConfig.bBBoxEnable)
|
||||
|
@ -27,6 +27,8 @@ enum ROOT_PARAMETER
|
||||
ROOT_PARAMETER_VS_CBV,
|
||||
ROOT_PARAMETER_VS_CBV2,
|
||||
ROOT_PARAMETER_GS_CBV,
|
||||
ROOT_PARAMETER_VS_SRV,
|
||||
ROOT_PARAMETER_BASE_VERTEX_CONSTANT,
|
||||
ROOT_PARAMETER_PS_UAV_OR_CBV2,
|
||||
ROOT_PARAMETER_PS_CBV2, // ROOT_PARAMETER_PS_UAV_OR_CBV2 if bbox is not enabled
|
||||
NUM_ROOT_PARAMETERS
|
||||
|
@ -165,6 +165,7 @@ std::unique_ptr<DXPipeline> DXPipeline::Create(const AbstractPipelineConfig& con
|
||||
switch (config.usage)
|
||||
{
|
||||
case AbstractPipelineUsage::GX:
|
||||
case AbstractPipelineUsage::GXUber:
|
||||
desc.pRootSignature = g_dx_context->GetGXRootSignature();
|
||||
break;
|
||||
case AbstractPipelineUsage::Utility:
|
||||
|
@ -87,6 +87,7 @@ void VideoBackend::FillBackendInfo()
|
||||
g_Config.backend_info.bSupportsLodBiasInSampler = true;
|
||||
g_Config.backend_info.bSupportsSettingObjectNames = true;
|
||||
g_Config.backend_info.bSupportsPartialMultisampleResolve = true;
|
||||
g_Config.backend_info.bSupportsDynamicVertexLoader = true;
|
||||
|
||||
// We can only check texture support once we have a device.
|
||||
if (g_dx_context)
|
||||
|
@ -220,7 +220,7 @@ static MTLCullMode Convert(CullMode cull)
|
||||
switch (cull)
|
||||
{
|
||||
case CullMode::None:
|
||||
case CullMode::All: // Handled by disabling rasterization
|
||||
case CullMode::All: // Handled by VertexLoaderManager::RunVertices
|
||||
return MTLCullModeNone;
|
||||
case CullMode::Front:
|
||||
return MTLCullModeFront;
|
||||
@ -289,7 +289,8 @@ public:
|
||||
}
|
||||
};
|
||||
template <size_t N>
|
||||
static void CopyAll(std::array<VertexAttribute, N>& output, const AttributeFormat (&input)[N])
|
||||
static void CopyAll(std::array<VertexAttribute, N>& output,
|
||||
const std::array<AttributeFormat, N>& input)
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
output[i] = VertexAttribute(input[i]);
|
||||
@ -327,13 +328,14 @@ public:
|
||||
blend.subtractAlpha = cfg.blending_state.subtractAlpha.Value();
|
||||
// clang-format on
|
||||
}
|
||||
// Throw extras in bits we don't otherwise use
|
||||
if (cfg.rasterization_state.cullmode == CullMode::All)
|
||||
blend.hex |= 1 << 29;
|
||||
if (cfg.rasterization_state.primitive == PrimitiveType::Points)
|
||||
blend.hex |= 1 << 30;
|
||||
else if (cfg.rasterization_state.primitive == PrimitiveType::Lines)
|
||||
blend.hex |= 1 << 31;
|
||||
|
||||
if (cfg.usage != AbstractPipelineUsage::GXUber)
|
||||
{
|
||||
if (cfg.rasterization_state.primitive == PrimitiveType::Points)
|
||||
is_points = true;
|
||||
else if (cfg.rasterization_state.primitive == PrimitiveType::Lines)
|
||||
is_lines = true;
|
||||
}
|
||||
}
|
||||
PipelineID() { memset(this, 0, sizeof(*this)); }
|
||||
PipelineID(const PipelineID& other) { memcpy(this, &other, sizeof(*this)); }
|
||||
@ -359,7 +361,13 @@ public:
|
||||
VertexAttribute v_posmtx;
|
||||
const Shader* vertex_shader;
|
||||
const Shader* fragment_shader;
|
||||
BlendingState blend;
|
||||
union
|
||||
{
|
||||
BlendingState blend;
|
||||
// Throw extras in bits we don't otherwise use
|
||||
BitField<30, 1, bool, u32> is_points;
|
||||
BitField<31, 1, bool, u32> is_lines;
|
||||
};
|
||||
FramebufferState framebuffer;
|
||||
};
|
||||
|
||||
@ -377,24 +385,17 @@ public:
|
||||
auto desc = MRCTransfer([MTLRenderPipelineDescriptor new]);
|
||||
[desc setVertexFunction:static_cast<const Shader*>(config.vertex_shader)->GetShader()];
|
||||
[desc setFragmentFunction:static_cast<const Shader*>(config.pixel_shader)->GetShader()];
|
||||
if (config.usage == AbstractPipelineUsage::GX)
|
||||
{
|
||||
if ([[[desc vertexFunction] label] containsString:@"Uber"])
|
||||
[desc
|
||||
setLabel:[NSString stringWithFormat:@"GX Uber Pipeline %d", m_pipeline_counter[0]++]];
|
||||
else
|
||||
[desc setLabel:[NSString stringWithFormat:@"GX Pipeline %d", m_pipeline_counter[1]++]];
|
||||
}
|
||||
if (config.usage == AbstractPipelineUsage::GXUber)
|
||||
[desc setLabel:[NSString stringWithFormat:@"GX Uber Pipeline %d", m_pipeline_counter[0]++]];
|
||||
else if (config.usage == AbstractPipelineUsage::GX)
|
||||
[desc setLabel:[NSString stringWithFormat:@"GX Pipeline %d", m_pipeline_counter[1]++]];
|
||||
else
|
||||
{
|
||||
[desc setLabel:[NSString stringWithFormat:@"Utility Pipeline %d", m_pipeline_counter[2]++]];
|
||||
}
|
||||
if (config.vertex_format)
|
||||
[desc setVertexDescriptor:static_cast<const VertexFormat*>(config.vertex_format)->Get()];
|
||||
RasterizationState rs = config.rasterization_state;
|
||||
[desc setInputPrimitiveTopology:GetClass(rs.primitive)];
|
||||
if (rs.cullmode == CullMode::All)
|
||||
[desc setRasterizationEnabled:NO];
|
||||
if (config.usage != AbstractPipelineUsage::GXUber)
|
||||
[desc setInputPrimitiveTopology:GetClass(rs.primitive)];
|
||||
MTLRenderPipelineColorAttachmentDescriptor* color0 =
|
||||
[[desc colorAttachments] objectAtIndexedSubscript:0];
|
||||
BlendingState bs = config.blending_state;
|
||||
|
@ -608,7 +608,7 @@ void Metal::StateTracker::PrepareRender()
|
||||
BeginRenderPass(MTLLoadActionLoad);
|
||||
id<MTLRenderCommandEncoder> enc = m_current_render_encoder;
|
||||
const Pipeline* pipe = m_state.render_pipeline;
|
||||
bool is_gx = pipe->Usage() == AbstractPipelineUsage::GX;
|
||||
bool is_gx = pipe->Usage() != AbstractPipelineUsage::Utility;
|
||||
NSString* label = is_gx ? LABEL_GX : LABEL_UTIL;
|
||||
if (m_flags.should_apply_label && m_current.label != label)
|
||||
{
|
||||
|
@ -74,6 +74,7 @@ void Metal::Util::PopulateBackendInfo(VideoConfig* config)
|
||||
config->backend_info.bSupportsSettingObjectNames = true;
|
||||
// Metal requires multisample resolve to be done on a render pass
|
||||
config->backend_info.bSupportsPartialMultisampleResolve = false;
|
||||
config->backend_info.bSupportsDynamicVertexLoader = true;
|
||||
}
|
||||
|
||||
void Metal::Util::PopulateBackendInfoAdapters(VideoConfig* config,
|
||||
@ -426,6 +427,7 @@ std::optional<std::string> Metal::Util::TranslateShaderToMSL(ShaderStage stage,
|
||||
static const spirv_cross::MSLResourceBinding resource_bindings[] = {
|
||||
MakeResourceBinding(spv::ExecutionModelVertex, 0, 0, 1, 0, 0), // vs/ubo
|
||||
MakeResourceBinding(spv::ExecutionModelVertex, 0, 1, 1, 0, 0), // vs/ubo
|
||||
MakeResourceBinding(spv::ExecutionModelVertex, 2, 1, 0, 0, 0), // vs/ssbo
|
||||
MakeResourceBinding(spv::ExecutionModelFragment, 0, 0, 0, 0, 0), // vs/ubo
|
||||
MakeResourceBinding(spv::ExecutionModelFragment, 0, 1, 1, 0, 0), // vs/ubo
|
||||
MakeResourceBinding(spv::ExecutionModelFragment, 1, 0, 0, 0, 0), // ps/samp0
|
||||
|
@ -125,7 +125,7 @@ static void SetAttribute(MTLVertexDescriptor* desc, u32 attribute, const Attribu
|
||||
|
||||
template <size_t N>
|
||||
static void SetAttributes(MTLVertexDescriptor* desc, u32 attribute,
|
||||
const AttributeFormat (&format)[N])
|
||||
const std::array<AttributeFormat, N>& format)
|
||||
{
|
||||
for (size_t i = 0; i < N; ++i)
|
||||
SetAttribute(desc, attribute + i, format[i]);
|
||||
|
@ -60,6 +60,7 @@ void VideoBackend::InitBackendInfo()
|
||||
g_Config.backend_info.bSupportsLodBiasInSampler = false;
|
||||
g_Config.backend_info.bSupportsSettingObjectNames = false;
|
||||
g_Config.backend_info.bSupportsPartialMultisampleResolve = true;
|
||||
g_Config.backend_info.bSupportsDynamicVertexLoader = false;
|
||||
|
||||
// aamodes: We only support 1 sample, so no MSAA
|
||||
g_Config.backend_info.Adapters.clear();
|
||||
|
@ -94,6 +94,8 @@ void VideoBackend::InitBackendInfo()
|
||||
g_Config.backend_info.bSupportsPipelineCacheData = false;
|
||||
g_Config.backend_info.bSupportsLodBiasInSampler = true;
|
||||
g_Config.backend_info.bSupportsPartialMultisampleResolve = true;
|
||||
// Unneccessary since OGL doesn't use pipelines
|
||||
g_Config.backend_info.bSupportsDynamicVertexLoader = false;
|
||||
|
||||
// TODO: There is a bug here, if texel buffers or SSBOs/atomics are not supported the graphics
|
||||
// options will show the option when it is not supported. The only way around this would be
|
||||
|
@ -89,6 +89,7 @@ void VideoSoftware::InitBackendInfo()
|
||||
g_Config.backend_info.bSupportsLodBiasInSampler = false;
|
||||
g_Config.backend_info.bSupportsSettingObjectNames = false;
|
||||
g_Config.backend_info.bSupportsPartialMultisampleResolve = true;
|
||||
g_Config.backend_info.bSupportsDynamicVertexLoader = false;
|
||||
|
||||
// aamodes
|
||||
g_Config.backend_info.AAModes = {1};
|
||||
|
@ -39,6 +39,8 @@ enum DESCRIPTOR_SET_LAYOUT
|
||||
// - Per-stage UBO (VS/GS/PS, VS constants accessible from PS) [set=0, binding=0-2]
|
||||
// - 8 combined image samplers (accessible from PS) [set=1, binding=0-7]
|
||||
// - 1 SSBO accessible from PS if supported [set=2, binding=0]
|
||||
// - Uber
|
||||
// - Like standard, plus 1 SSBO accessible from VS if supported [set=2, binding=1]
|
||||
// - Utility
|
||||
// - 1 combined UBO, accessible from VS/GS/PS [set=0, binding=0]
|
||||
// - 8 combined image samplers (accessible from PS) [set=1, binding=0-7]
|
||||
@ -55,6 +57,7 @@ enum DESCRIPTOR_SET_LAYOUT
|
||||
enum PIPELINE_LAYOUT
|
||||
{
|
||||
PIPELINE_LAYOUT_STANDARD,
|
||||
PIPELINE_LAYOUT_UBER,
|
||||
PIPELINE_LAYOUT_UTILITY,
|
||||
PIPELINE_LAYOUT_COMPUTE,
|
||||
NUM_PIPELINE_LAYOUTS
|
||||
|
@ -123,8 +123,10 @@ bool ObjectCache::CreateDescriptorSetLayouts()
|
||||
VK_SHADER_STAGE_FRAGMENT_BIT},
|
||||
}};
|
||||
|
||||
static const std::array<VkDescriptorSetLayoutBinding, 1> standard_ssbo_bindings{{
|
||||
// The dynamic veretex loader's vertex buffer must be last here, for similar reasons
|
||||
static const std::array<VkDescriptorSetLayoutBinding, 2> standard_ssbo_bindings{{
|
||||
{0, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_FRAGMENT_BIT},
|
||||
{1, VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, 1, VK_SHADER_STAGE_VERTEX_BIT},
|
||||
}};
|
||||
|
||||
static const std::array<VkDescriptorSetLayoutBinding, 1> utility_ubo_bindings{{
|
||||
@ -173,6 +175,10 @@ bool ObjectCache::CreateDescriptorSetLayouts()
|
||||
if (!g_ActiveConfig.backend_info.bSupportsGeometryShaders)
|
||||
create_infos[DESCRIPTOR_SET_LAYOUT_STANDARD_UNIFORM_BUFFERS].bindingCount--;
|
||||
|
||||
// Remove the dynamic vertex loader's buffer if it'll never be needed
|
||||
if (!g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader)
|
||||
create_infos[DESCRIPTOR_SET_LAYOUT_STANDARD_SHADER_STORAGE_BUFFERS].bindingCount--;
|
||||
|
||||
for (size_t i = 0; i < create_infos.size(); i++)
|
||||
{
|
||||
VkResult res = vkCreateDescriptorSetLayout(g_vulkan_context->GetDevice(), &create_infos[i],
|
||||
@ -206,6 +212,11 @@ bool ObjectCache::CreatePipelineLayouts()
|
||||
m_descriptor_set_layouts[DESCRIPTOR_SET_LAYOUT_STANDARD_SAMPLERS],
|
||||
m_descriptor_set_layouts[DESCRIPTOR_SET_LAYOUT_STANDARD_SHADER_STORAGE_BUFFERS],
|
||||
};
|
||||
const std::array<VkDescriptorSetLayout, 3> uber_sets{
|
||||
m_descriptor_set_layouts[DESCRIPTOR_SET_LAYOUT_STANDARD_UNIFORM_BUFFERS],
|
||||
m_descriptor_set_layouts[DESCRIPTOR_SET_LAYOUT_STANDARD_SAMPLERS],
|
||||
m_descriptor_set_layouts[DESCRIPTOR_SET_LAYOUT_STANDARD_SHADER_STORAGE_BUFFERS],
|
||||
};
|
||||
const std::array<VkDescriptorSetLayout, 2> utility_sets{
|
||||
m_descriptor_set_layouts[DESCRIPTOR_SET_LAYOUT_UTILITY_UNIFORM_BUFFER],
|
||||
m_descriptor_set_layouts[DESCRIPTOR_SET_LAYOUT_UTILITY_SAMPLERS],
|
||||
@ -220,6 +231,10 @@ bool ObjectCache::CreatePipelineLayouts()
|
||||
{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, nullptr, 0,
|
||||
static_cast<u32>(standard_sets.size()), standard_sets.data(), 0, nullptr},
|
||||
|
||||
// Uber
|
||||
{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, nullptr, 0,
|
||||
static_cast<u32>(uber_sets.size()), uber_sets.data(), 0, nullptr},
|
||||
|
||||
// Utility
|
||||
{VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO, nullptr, 0,
|
||||
static_cast<u32>(utility_sets.size()), utility_sets.data(), 0, nullptr},
|
||||
@ -232,6 +247,10 @@ bool ObjectCache::CreatePipelineLayouts()
|
||||
// If bounding box is unsupported, don't bother with the SSBO descriptor set.
|
||||
if (!g_ActiveConfig.backend_info.bSupportsBBox)
|
||||
pipeline_layout_info[PIPELINE_LAYOUT_STANDARD].setLayoutCount--;
|
||||
// If neither SSBO-using feature is supported, skip in ubershaders too
|
||||
if (!g_ActiveConfig.backend_info.bSupportsBBox &&
|
||||
!g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader)
|
||||
pipeline_layout_info[PIPELINE_LAYOUT_UBER].setLayoutCount--;
|
||||
|
||||
for (size_t i = 0; i < pipeline_layout_info.size(); i++)
|
||||
{
|
||||
|
@ -77,14 +77,23 @@ bool StateTracker::Initialize()
|
||||
return true;
|
||||
}
|
||||
|
||||
void StateTracker::SetVertexBuffer(VkBuffer buffer, VkDeviceSize offset)
|
||||
void StateTracker::SetVertexBuffer(VkBuffer buffer, VkDeviceSize offset, u32 size)
|
||||
{
|
||||
if (m_vertex_buffer == buffer && m_vertex_buffer_offset == offset)
|
||||
return;
|
||||
|
||||
m_vertex_buffer = buffer;
|
||||
m_vertex_buffer_offset = offset;
|
||||
m_dirty_flags |= DIRTY_FLAG_VERTEX_BUFFER;
|
||||
if (m_vertex_buffer != buffer || m_vertex_buffer_offset != offset)
|
||||
{
|
||||
m_vertex_buffer = buffer;
|
||||
m_vertex_buffer_offset = offset;
|
||||
m_dirty_flags |= DIRTY_FLAG_VERTEX_BUFFER;
|
||||
}
|
||||
if (m_bindings.gx_uber_vertex_ssbo.buffer != buffer ||
|
||||
m_bindings.gx_uber_vertex_ssbo.offset != offset ||
|
||||
m_bindings.gx_uber_vertex_ssbo.range != size)
|
||||
{
|
||||
m_bindings.gx_uber_vertex_ssbo.buffer = buffer;
|
||||
m_bindings.gx_uber_vertex_ssbo.offset = offset;
|
||||
m_bindings.gx_uber_vertex_ssbo.range = size;
|
||||
m_dirty_flags |= DIRTY_FLAG_GX_SSBO;
|
||||
}
|
||||
}
|
||||
|
||||
void StateTracker::SetIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType type)
|
||||
@ -366,8 +375,13 @@ bool StateTracker::Bind()
|
||||
|
||||
// Re-bind parts of the pipeline
|
||||
const VkCommandBuffer command_buffer = g_command_buffer_mgr->GetCurrentCommandBuffer();
|
||||
if (m_dirty_flags & DIRTY_FLAG_VERTEX_BUFFER)
|
||||
const bool needs_vertex_buffer = !g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader ||
|
||||
m_pipeline->GetUsage() != AbstractPipelineUsage::GXUber;
|
||||
if (needs_vertex_buffer && (m_dirty_flags & DIRTY_FLAG_VERTEX_BUFFER))
|
||||
{
|
||||
vkCmdBindVertexBuffers(command_buffer, 0, 1, &m_vertex_buffer, &m_vertex_buffer_offset);
|
||||
m_dirty_flags &= ~DIRTY_FLAG_VERTEX_BUFFER;
|
||||
}
|
||||
|
||||
if (m_dirty_flags & DIRTY_FLAG_INDEX_BUFFER)
|
||||
vkCmdBindIndexBuffer(command_buffer, m_index_buffer, m_index_buffer_offset, m_index_type);
|
||||
@ -381,8 +395,8 @@ bool StateTracker::Bind()
|
||||
if (m_dirty_flags & DIRTY_FLAG_SCISSOR)
|
||||
vkCmdSetScissor(command_buffer, 0, 1, &m_scissor);
|
||||
|
||||
m_dirty_flags &= ~(DIRTY_FLAG_VERTEX_BUFFER | DIRTY_FLAG_INDEX_BUFFER | DIRTY_FLAG_PIPELINE |
|
||||
DIRTY_FLAG_VIEWPORT | DIRTY_FLAG_SCISSOR);
|
||||
m_dirty_flags &=
|
||||
~(DIRTY_FLAG_INDEX_BUFFER | DIRTY_FLAG_PIPELINE | DIRTY_FLAG_VIEWPORT | DIRTY_FLAG_SCISSOR);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -452,7 +466,7 @@ void StateTracker::EndClearRenderPass()
|
||||
|
||||
bool StateTracker::UpdateDescriptorSet()
|
||||
{
|
||||
if (m_pipeline->GetUsage() == AbstractPipelineUsage::GX)
|
||||
if (m_pipeline->GetUsage() != AbstractPipelineUsage::Utility)
|
||||
return UpdateGXDescriptorSet();
|
||||
else
|
||||
return UpdateUtilityDescriptorSet();
|
||||
@ -462,7 +476,7 @@ bool StateTracker::UpdateGXDescriptorSet()
|
||||
{
|
||||
const size_t MAX_DESCRIPTOR_WRITES = NUM_UBO_DESCRIPTOR_SET_BINDINGS + // UBO
|
||||
1 + // Samplers
|
||||
1; // SSBO
|
||||
2; // SSBO
|
||||
std::array<VkWriteDescriptorSet, MAX_DESCRIPTOR_WRITES> writes;
|
||||
u32 num_writes = 0;
|
||||
|
||||
@ -516,7 +530,12 @@ bool StateTracker::UpdateGXDescriptorSet()
|
||||
m_dirty_flags = (m_dirty_flags & ~DIRTY_FLAG_GX_SAMPLERS) | DIRTY_FLAG_DESCRIPTOR_SETS;
|
||||
}
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsBBox &&
|
||||
const bool needs_bbox_ssbo = g_ActiveConfig.backend_info.bSupportsBBox;
|
||||
const bool needs_vertex_ssbo = g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader &&
|
||||
m_pipeline->GetUsage() == AbstractPipelineUsage::GXUber;
|
||||
const bool needs_ssbo = needs_bbox_ssbo || needs_vertex_ssbo;
|
||||
|
||||
if (needs_ssbo &&
|
||||
(m_dirty_flags & DIRTY_FLAG_GX_SSBO || m_gx_descriptor_sets[2] == VK_NULL_HANDLE))
|
||||
{
|
||||
m_gx_descriptor_sets[2] =
|
||||
@ -528,6 +547,21 @@ bool StateTracker::UpdateGXDescriptorSet()
|
||||
writes[num_writes++] = {
|
||||
VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET, nullptr, m_gx_descriptor_sets[2], 0, 0, 1,
|
||||
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, nullptr, &m_bindings.ssbo, nullptr};
|
||||
|
||||
if (g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader)
|
||||
{
|
||||
writes[num_writes++] = {VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
|
||||
nullptr,
|
||||
m_gx_descriptor_sets[2],
|
||||
1,
|
||||
0,
|
||||
1,
|
||||
VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
|
||||
nullptr,
|
||||
&m_bindings.gx_uber_vertex_ssbo,
|
||||
nullptr};
|
||||
}
|
||||
|
||||
m_dirty_flags = (m_dirty_flags & ~DIRTY_FLAG_GX_SSBO) | DIRTY_FLAG_DESCRIPTOR_SETS;
|
||||
}
|
||||
|
||||
@ -538,9 +572,7 @@ bool StateTracker::UpdateGXDescriptorSet()
|
||||
{
|
||||
vkCmdBindDescriptorSets(g_command_buffer_mgr->GetCurrentCommandBuffer(),
|
||||
VK_PIPELINE_BIND_POINT_GRAPHICS, m_pipeline->GetVkPipelineLayout(), 0,
|
||||
g_ActiveConfig.backend_info.bSupportsBBox ?
|
||||
NUM_GX_DESCRIPTOR_SETS :
|
||||
(NUM_GX_DESCRIPTOR_SETS - 1),
|
||||
needs_ssbo ? NUM_GX_DESCRIPTOR_SETS : (NUM_GX_DESCRIPTOR_SETS - 1),
|
||||
m_gx_descriptor_sets.data(),
|
||||
g_ActiveConfig.backend_info.bSupportsGeometryShaders ?
|
||||
NUM_UBO_DESCRIPTOR_SET_BINDINGS :
|
||||
|
@ -32,7 +32,7 @@ public:
|
||||
|
||||
VKFramebuffer* GetFramebuffer() const { return m_framebuffer; }
|
||||
const VKPipeline* GetPipeline() const { return m_pipeline; }
|
||||
void SetVertexBuffer(VkBuffer buffer, VkDeviceSize offset);
|
||||
void SetVertexBuffer(VkBuffer buffer, VkDeviceSize offset, u32 size);
|
||||
void SetIndexBuffer(VkBuffer buffer, VkDeviceSize offset, VkIndexType type);
|
||||
void SetFramebuffer(VKFramebuffer* framebuffer);
|
||||
void SetPipeline(const VKPipeline* pipeline);
|
||||
@ -145,6 +145,7 @@ private:
|
||||
std::array<VkDescriptorImageInfo, NUM_PIXEL_SHADER_SAMPLERS> samplers;
|
||||
std::array<VkBufferView, NUM_COMPUTE_TEXEL_BUFFERS> texel_buffers;
|
||||
VkDescriptorBufferInfo ssbo;
|
||||
VkDescriptorBufferInfo gx_uber_vertex_ssbo;
|
||||
VkDescriptorImageInfo image_texture;
|
||||
} m_bindings = {};
|
||||
std::array<VkDescriptorSet, NUM_GX_DESCRIPTOR_SETS> m_gx_descriptor_sets = {};
|
||||
|
@ -251,6 +251,9 @@ std::unique_ptr<VKPipeline> VKPipeline::Create(const AbstractPipelineConfig& con
|
||||
case AbstractPipelineUsage::GX:
|
||||
pipeline_layout = g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_STANDARD);
|
||||
break;
|
||||
case AbstractPipelineUsage::GXUber:
|
||||
pipeline_layout = g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_UBER);
|
||||
break;
|
||||
case AbstractPipelineUsage::Utility:
|
||||
pipeline_layout = g_object_cache->GetPipelineLayout(PIPELINE_LAYOUT_UTILITY);
|
||||
break;
|
||||
|
@ -62,7 +62,8 @@ bool VertexManager::Initialize()
|
||||
return false;
|
||||
|
||||
m_vertex_stream_buffer =
|
||||
StreamBuffer::Create(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, VERTEX_STREAM_BUFFER_SIZE);
|
||||
StreamBuffer::Create(VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT,
|
||||
VERTEX_STREAM_BUFFER_SIZE);
|
||||
m_index_stream_buffer =
|
||||
StreamBuffer::Create(VK_BUFFER_USAGE_INDEX_BUFFER_BIT, INDEX_STREAM_BUFFER_SIZE);
|
||||
m_uniform_stream_buffer =
|
||||
@ -186,7 +187,8 @@ void VertexManager::CommitBuffer(u32 num_vertices, u32 vertex_stride, u32 num_in
|
||||
ADDSTAT(g_stats.this_frame.bytes_vertex_streamed, static_cast<int>(vertex_data_size));
|
||||
ADDSTAT(g_stats.this_frame.bytes_index_streamed, static_cast<int>(index_data_size));
|
||||
|
||||
StateTracker::GetInstance()->SetVertexBuffer(m_vertex_stream_buffer->GetBuffer(), 0);
|
||||
StateTracker::GetInstance()->SetVertexBuffer(m_vertex_stream_buffer->GetBuffer(), 0,
|
||||
VERTEX_STREAM_BUFFER_SIZE);
|
||||
StateTracker::GetInstance()->SetIndexBuffer(m_index_stream_buffer->GetBuffer(), 0,
|
||||
VK_INDEX_TYPE_UINT16);
|
||||
}
|
||||
|
@ -295,6 +295,7 @@ void VulkanContext::PopulateBackendInfo(VideoConfig* config)
|
||||
config->backend_info.bSupportsLodBiasInSampler = false; // Dependent on OS.
|
||||
config->backend_info.bSupportsSettingObjectNames = false; // Dependent on features.
|
||||
config->backend_info.bSupportsPartialMultisampleResolve = true; // Assumed support.
|
||||
config->backend_info.bSupportsDynamicVertexLoader = true; // Assumed support.
|
||||
}
|
||||
|
||||
void VulkanContext::PopulateBackendInfoAdapters(VideoConfig* config, const GPUList& gpu_list)
|
||||
|
@ -20,6 +20,8 @@ class NativeVertexFormat;
|
||||
// - Per-stage UBO (VS/GS/PS, VS constants accessible from PS)
|
||||
// - 8 combined image samplers (accessible from PS)
|
||||
// - 1 SSBO, accessible from PS if bounding box is enabled
|
||||
// - GX Uber
|
||||
// - Same as GX, plus one VS SSBO for vertices if dynamic vertex loading is enabled
|
||||
// - Utility
|
||||
// - Single UBO, accessible from all stages [set=0, binding=1]
|
||||
// - 8 combined image samplers (accessible from PS) [set=1, binding=0-7]
|
||||
@ -32,6 +34,7 @@ class NativeVertexFormat;
|
||||
enum class AbstractPipelineUsage
|
||||
{
|
||||
GX,
|
||||
GXUber,
|
||||
Utility
|
||||
};
|
||||
|
||||
|
@ -93,6 +93,13 @@ struct VertexShaderConstants
|
||||
|
||||
float4 cached_tangent;
|
||||
float4 cached_binormal;
|
||||
// For UberShader vertex loader
|
||||
u32 vertex_stride;
|
||||
std::array<u32, 3> vertex_offset_normals;
|
||||
u32 vertex_offset_position;
|
||||
u32 vertex_offset_posmtx;
|
||||
std::array<u32, 2> vertex_offset_colors;
|
||||
std::array<u32, 8> vertex_offset_texcoords;
|
||||
};
|
||||
|
||||
struct GeometryShaderConstants
|
||||
|
@ -58,9 +58,9 @@ struct PortableVertexDeclaration
|
||||
int stride;
|
||||
|
||||
AttributeFormat position;
|
||||
AttributeFormat normals[3];
|
||||
AttributeFormat colors[2];
|
||||
AttributeFormat texcoords[8];
|
||||
std::array<AttributeFormat, 3> normals;
|
||||
std::array<AttributeFormat, 2> colors;
|
||||
std::array<AttributeFormat, 8> texcoords;
|
||||
AttributeFormat posmtx;
|
||||
|
||||
inline bool operator<(const PortableVertexDeclaration& b) const
|
||||
|
@ -122,7 +122,7 @@ public:
|
||||
// HACK
|
||||
DataReader src{const_cast<u8*>(vertex_data), const_cast<u8*>(vertex_data) + size};
|
||||
const u32 bytes =
|
||||
VertexLoaderManager::RunVertices(vat, primitive, num_vertices, src, is_preprocess);
|
||||
VertexLoaderManager::RunVertices<is_preprocess>(vat, primitive, num_vertices, src);
|
||||
|
||||
ASSERT(bytes == size);
|
||||
|
||||
@ -228,6 +228,12 @@ public:
|
||||
return g_main_cp_state;
|
||||
}
|
||||
|
||||
OPCODE_CALLBACK(u32 GetVertexSize(u8 vat))
|
||||
{
|
||||
VertexLoaderBase* loader = VertexLoaderManager::RefreshLoader<is_preprocess>(vat);
|
||||
return loader->m_vertex_size;
|
||||
}
|
||||
|
||||
u32 m_cycles = 0;
|
||||
bool m_in_display_list = false;
|
||||
};
|
||||
|
@ -110,6 +110,8 @@ public:
|
||||
|
||||
// Get the current CP state. Needed for vertex decoding; will also be mutated for CP commands.
|
||||
virtual CPState& GetCPState() = 0;
|
||||
|
||||
virtual u32 GetVertexSize(u8 vat) = 0;
|
||||
#endif
|
||||
};
|
||||
|
||||
@ -229,8 +231,7 @@ static DOLPHIN_FORCE_INLINE u32 RunCommand(const u8* data, u32 available, T& cal
|
||||
(cmdbyte & OpcodeDecoder::GX_PRIMITIVE_MASK) >> OpcodeDecoder::GX_PRIMITIVE_SHIFT);
|
||||
const u8 vat = cmdbyte & OpcodeDecoder::GX_VAT_MASK;
|
||||
|
||||
const u32 vertex_size = VertexLoaderBase::GetVertexSize(callback.GetCPState().vtx_desc,
|
||||
callback.GetCPState().vtx_attr[vat]);
|
||||
const u32 vertex_size = callback.GetVertexSize(vat);
|
||||
const u16 num_vertices = Common::swap16(&data[1]);
|
||||
|
||||
if (available < 3 + num_vertices * vertex_size)
|
||||
|
@ -588,10 +588,10 @@ AbstractPipelineConfig ShaderCache::GetGXPipelineConfig(
|
||||
const NativeVertexFormat* vertex_format, const AbstractShader* vertex_shader,
|
||||
const AbstractShader* geometry_shader, const AbstractShader* pixel_shader,
|
||||
const RasterizationState& rasterization_state, const DepthState& depth_state,
|
||||
const BlendingState& blending_state)
|
||||
const BlendingState& blending_state, AbstractPipelineUsage usage)
|
||||
{
|
||||
AbstractPipelineConfig config = {};
|
||||
config.usage = AbstractPipelineUsage::GX;
|
||||
config.usage = usage;
|
||||
config.vertex_format = vertex_format;
|
||||
config.vertex_shader = vertex_shader;
|
||||
config.geometry_shader = geometry_shader;
|
||||
@ -735,7 +735,7 @@ ShaderCache::GetGXPipelineConfig(const GXPipelineUid& config_in)
|
||||
}
|
||||
|
||||
return GetGXPipelineConfig(config.vertex_format, vs, gs, ps, config.rasterization_state,
|
||||
config.depth_state, config.blending_state);
|
||||
config.depth_state, config.blending_state, AbstractPipelineUsage::GX);
|
||||
}
|
||||
|
||||
/// Edits the UID based on driver bugs and other special configurations
|
||||
@ -743,6 +743,8 @@ static GXUberPipelineUid ApplyDriverBugs(const GXUberPipelineUid& in)
|
||||
{
|
||||
GXUberPipelineUid out;
|
||||
memcpy(&out, &in, sizeof(out)); // Copy padding
|
||||
if (g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader)
|
||||
out.vertex_format = nullptr;
|
||||
if (g_ActiveConfig.backend_info.bSupportsFramebufferFetch)
|
||||
{
|
||||
// Always blend in shader
|
||||
@ -798,7 +800,8 @@ ShaderCache::GetGXPipelineConfig(const GXUberPipelineUid& config_in)
|
||||
}
|
||||
|
||||
return GetGXPipelineConfig(config.vertex_format, vs, gs, ps, config.rasterization_state,
|
||||
config.depth_state, config.blending_state);
|
||||
config.depth_state, config.blending_state,
|
||||
AbstractPipelineUsage::GXUber);
|
||||
}
|
||||
|
||||
const AbstractPipeline* ShaderCache::InsertGXPipeline(const GXPipelineUid& config,
|
||||
@ -1233,32 +1236,32 @@ void ShaderCache::QueueUberShaderPipelines()
|
||||
dummy_vertex_decl.stride = sizeof(float) * 4;
|
||||
NativeVertexFormat* dummy_vertex_format =
|
||||
VertexLoaderManager::GetUberVertexFormat(dummy_vertex_decl);
|
||||
auto QueueDummyPipeline = [&](const UberShader::VertexShaderUid& vs_uid,
|
||||
const GeometryShaderUid& gs_uid,
|
||||
const UberShader::PixelShaderUid& ps_uid) {
|
||||
GXUberPipelineUid config;
|
||||
config.vertex_format = dummy_vertex_format;
|
||||
config.vs_uid = vs_uid;
|
||||
config.gs_uid = gs_uid;
|
||||
config.ps_uid = ps_uid;
|
||||
config.rasterization_state = RenderState::GetCullBackFaceRasterizationState(
|
||||
static_cast<PrimitiveType>(gs_uid.GetUidData()->primitive_type));
|
||||
config.depth_state = RenderState::GetNoDepthTestingDepthState();
|
||||
config.blending_state = RenderState::GetNoBlendingBlendState();
|
||||
if (ps_uid.GetUidData()->uint_output)
|
||||
{
|
||||
// uint_output is only ever enabled when logic ops are enabled.
|
||||
config.blending_state.logicopenable = true;
|
||||
config.blending_state.logicmode = LogicOp::And;
|
||||
}
|
||||
auto QueueDummyPipeline =
|
||||
[&](const UberShader::VertexShaderUid& vs_uid, const GeometryShaderUid& gs_uid,
|
||||
const UberShader::PixelShaderUid& ps_uid, const BlendingState& blend) {
|
||||
GXUberPipelineUid config;
|
||||
config.vertex_format = dummy_vertex_format;
|
||||
config.vs_uid = vs_uid;
|
||||
config.gs_uid = gs_uid;
|
||||
config.ps_uid = ps_uid;
|
||||
config.rasterization_state = RenderState::GetCullBackFaceRasterizationState(
|
||||
static_cast<PrimitiveType>(gs_uid.GetUidData()->primitive_type));
|
||||
config.depth_state = RenderState::GetNoDepthTestingDepthState();
|
||||
config.blending_state = blend;
|
||||
if (ps_uid.GetUidData()->uint_output)
|
||||
{
|
||||
// uint_output is only ever enabled when logic ops are enabled.
|
||||
config.blending_state.logicopenable = true;
|
||||
config.blending_state.logicmode = LogicOp::And;
|
||||
}
|
||||
|
||||
auto iter = m_gx_uber_pipeline_cache.find(config);
|
||||
if (iter != m_gx_uber_pipeline_cache.end())
|
||||
return;
|
||||
auto iter = m_gx_uber_pipeline_cache.find(config);
|
||||
if (iter != m_gx_uber_pipeline_cache.end())
|
||||
return;
|
||||
|
||||
auto& entry = m_gx_uber_pipeline_cache[config];
|
||||
entry.second = false;
|
||||
};
|
||||
auto& entry = m_gx_uber_pipeline_cache[config];
|
||||
entry.second = false;
|
||||
};
|
||||
|
||||
// Populate the pipeline configs with empty entries, these will be compiled afterwards.
|
||||
UberShader::EnumerateVertexShaderUids([&](const UberShader::VertexShaderUid& vuid) {
|
||||
@ -1275,7 +1278,45 @@ void ShaderCache::QueueUberShaderPipelines()
|
||||
{
|
||||
return;
|
||||
}
|
||||
QueueDummyPipeline(vuid, guid, cleared_puid);
|
||||
BlendingState blend = RenderState::GetNoBlendingBlendState();
|
||||
QueueDummyPipeline(vuid, guid, cleared_puid, blend);
|
||||
if (g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader)
|
||||
{
|
||||
// Not all GPUs need all the pipeline state compiled into shaders, so they tend to key
|
||||
// compiled shaders based on some subset of the pipeline state.
|
||||
// Some test results:
|
||||
// (GPUs tested: AMD Radeon Pro 5600M, Nvidia GT 750M, Intel UHD 630,
|
||||
// Intel Iris Pro 5200, Apple M1)
|
||||
// MacOS Metal:
|
||||
// - AMD, Nvidia, Intel GPUs: Shaders are keyed on vertex layout and whether or not
|
||||
// dual source blend is enabled. That's it.
|
||||
// - Apple GPUs: Shaders are keyed on vertex layout and all blending settings. We use
|
||||
// framebuffer fetch here, so the only blending settings used by ubershaders are the
|
||||
// alphaupdate and colorupdate ones. Also keyed on primitive type, but Metal supports
|
||||
// setting it to "unknown" and we do for ubershaders (but MoltenVK won't).
|
||||
// Windows Vulkan:
|
||||
// - AMD, Nvidia: Definitely keyed on dual source blend, but the others seem more random
|
||||
// Changing a setting on one shader will require a recompile, but changing the same
|
||||
// setting on another won't. Compiling a copy with alphaupdate off, colorupdate off,
|
||||
// and one with DSB on seems to get pretty good coverage though.
|
||||
// Windows D3D12:
|
||||
// - AMD: Keyed on dual source blend and vertex layout
|
||||
// - Nvidia Kepler: No recompiles for changes to vertex layout or blend
|
||||
blend.alphaupdate = false;
|
||||
QueueDummyPipeline(vuid, guid, cleared_puid, blend);
|
||||
blend.alphaupdate = true;
|
||||
blend.colorupdate = false;
|
||||
QueueDummyPipeline(vuid, guid, cleared_puid, blend);
|
||||
blend.colorupdate = true;
|
||||
if (!cleared_puid.GetUidData()->no_dual_src && !cleared_puid.GetUidData()->uint_output)
|
||||
{
|
||||
blend.blendenable = true;
|
||||
blend.usedualsrc = true;
|
||||
blend.srcfactor = SrcBlendFactor::SrcAlpha;
|
||||
blend.dstfactor = DstBlendFactor::InvSrcAlpha;
|
||||
QueueDummyPipeline(vuid, guid, cleared_puid, blend);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
|
@ -151,7 +151,7 @@ private:
|
||||
GetGXPipelineConfig(const NativeVertexFormat* vertex_format, const AbstractShader* vertex_shader,
|
||||
const AbstractShader* geometry_shader, const AbstractShader* pixel_shader,
|
||||
const RasterizationState& rasterization_state, const DepthState& depth_state,
|
||||
const BlendingState& blending_state);
|
||||
const BlendingState& blending_state, AbstractPipelineUsage usage);
|
||||
std::optional<AbstractPipelineConfig> GetGXPipelineConfig(const GXPipelineUid& uid);
|
||||
std::optional<AbstractPipelineConfig> GetGXPipelineConfig(const GXUberPipelineUid& uid);
|
||||
const AbstractPipeline* InsertGXPipeline(const GXPipelineUid& config,
|
||||
|
@ -43,6 +43,7 @@ ShaderHostConfig ShaderHostConfig::GetCurrent()
|
||||
bits.manual_texture_sampling_custom_texture_sizes =
|
||||
g_ActiveConfig.ManualTextureSamplingWithHiResTextures();
|
||||
bits.backend_sampler_lod_bias = g_ActiveConfig.backend_info.bSupportsLodBiasInSampler;
|
||||
bits.backend_dynamic_vertex_loader = g_ActiveConfig.backend_info.bSupportsDynamicVertexLoader;
|
||||
return bits;
|
||||
}
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
Reference in New Issue
Block a user