Updated to 5.0-17430 for more optimisations!

This commit is contained in:
sirmangler 2022-09-24 14:55:45 +01:00
commit aaa54ae2a7
124 changed files with 2350 additions and 1635 deletions

View File

@ -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"

View File

@ -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)

View File

@ -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.

View File

@ -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

View File

@ -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);
}
}

View File

@ -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());

View File

@ -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.");
}
}
}

View File

@ -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" />

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -110,11 +110,10 @@
</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" />

View File

@ -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>

View File

@ -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 -->

View File

@ -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

View File

@ -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); }

View File

@ -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);

View File

@ -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

View File

@ -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);

View File

@ -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()

View File

@ -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;

View File

@ -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,

View File

@ -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)

View File

@ -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);

View File

@ -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))
{

View File

@ -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 */>

View File

@ -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,

View File

@ -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();

View File

@ -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

View File

@ -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;
}

View File

@ -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);

View File

@ -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())
{
if (!WaitForWiimoteBuffer(_number))
return false;
}
// wait for receiving thread to push some data
m_wii_pad_event.Wait();
}
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())
{
if (!WaitForWiimoteBuffer(_number))
return false;
}
// wait for receiving thread to push some data
m_wii_pad_event.Wait();
}
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;
}

View File

@ -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);

View File

@ -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,
};

View File

@ -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)
{
// load host's GC SRAM
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);
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())

View File

@ -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))
{

View File

@ -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;

View File

@ -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,

View File

@ -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

View File

@ -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();

View File

@ -1432,6 +1432,7 @@ void VolumeVerifier::Finish()
}
else
{
m_result.summary_text =
Common::GetStringT("Problems with low severity were found. They will most "
"likely not prevent the game from running.");
}

View File

@ -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()

View File

@ -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);
}
}
void GamecubeControllersWidget::OnGCTypeChanged(int type)
{
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;
}
}
[this, i] {
OnGCTypeChanged(i);
SaveSettings();
});
connect(m_gc_buttons[i], &QPushButton::clicked, this, [this, i] { OnGCPadConfigure(i); });
}
}
void GamecubeControllersWidget::OnGCPadConfigure()
void GamecubeControllersWidget::OnGCTypeChanged(size_t index)
{
size_t index;
for (index = 0; index < m_gc_groups.size(); index++)
{
if (m_gc_buttons[index] == QObject::sender())
break;
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(size_t index)
{
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::ConfigChangeCallbackGuard config_guard;
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);
if (Core::IsRunning())
SerialInterface::ChangeDevice(si_device, static_cast<s32>(i));
m_gc_buttons[i]->setEnabled(IsConfigurable(si_device));
}
if (GCAdapter::UseAdapter())
GCAdapter::StartScanThread();
else
GCAdapter::StopScanThread();
}
SConfig::GetInstance().SaveSettings();
}

View File

@ -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();

View File

@ -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);

View File

@ -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);
}

View File

@ -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);
}

View File

@ -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,59 +186,13 @@ 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_buttons[i], &QPushButton::clicked, this,
&WiimoteControllersWidget::OnWiimoteConfigure);
}
}
void WiimoteControllersWidget::OnWiimoteModeChanged()
{
connect(m_wiimote_boxes[i], qOverload<int>(&QComboBox::currentIndexChanged), this, [this] {
SaveSettings();
// Make sure continuous scanning setting is applied.
WiimoteReal::Initialize(::Wiimote::InitializeMode::DO_NOT_WAIT_FOR_WIIMOTES);
UpdateDisabledWiimoteControls();
LoadSettings(Core::GetState());
});
connect(m_wiimote_buttons[i], &QPushButton::clicked, this,
[this, i] { OnWiimoteConfigure(i); });
}
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()
@ -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,28 +273,68 @@ 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::ConfigChangeCallbackGuard config_guard;
Config::SetBaseOrCurrent(Config::MAIN_WIIMOTE_ENABLE_SPEAKER,
m_wiimote_speaker_data->isChecked());
Config::SetBaseOrCurrent(Config::MAIN_CONNECT_WIIMOTES_FOR_CONTROLLER_INTERFACE,
@ -360,6 +353,7 @@ void WiimoteControllersWidget::SaveSettings()
const int index = m_wiimote_boxes[i]->currentIndex();
Config::SetBaseOrCurrent(Config::GetInfoForWiimoteSource(int(i)), WiimoteSource(index));
}
}
SConfig::GetInstance().SaveSettings();
}

View File

@ -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;

View File

@ -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);

View File

@ -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;

View File

@ -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;
};

View File

@ -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()));
});
}

View File

@ -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); });
}
}

View File

@ -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());
}

View File

@ -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);
}

View File

@ -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,

View File

@ -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);

View File

@ -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()

View File

@ -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:

View File

@ -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);

View File

@ -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);

View File

@ -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,19 +500,23 @@ 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;
}
}
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;

View File

@ -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 = {};

View File

@ -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);

View File

@ -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

View File

@ -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(&params[param_count], 0, D3D12_SHADER_VISIBILITY_GEOMETRY);
param_count++;
SetRootParamTable(&params[param_count], &ranges[param_count], D3D12_DESCRIPTOR_RANGE_TYPE_SRV, 3,
1, D3D12_SHADER_VISIBILITY_VERTEX);
param_count++;
SetRootParamConstant(&params[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)

View File

@ -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

View File

@ -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:

View File

@ -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)

View File

@ -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.usage != AbstractPipelineUsage::GXUber)
{
if (cfg.rasterization_state.primitive == PrimitiveType::Points)
blend.hex |= 1 << 30;
is_points = true;
else if (cfg.rasterization_state.primitive == PrimitiveType::Lines)
blend.hex |= 1 << 31;
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;
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
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;
if (config.usage != AbstractPipelineUsage::GXUber)
[desc setInputPrimitiveTopology:GetClass(rs.primitive)];
if (rs.cullmode == CullMode::All)
[desc setRasterizationEnabled:NO];
MTLRenderPipelineColorAttachmentDescriptor* color0 =
[[desc colorAttachments] objectAtIndexedSubscript:0];
BlendingState bs = config.blending_state;

View File

@ -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)
{

View File

@ -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

View File

@ -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]);

View File

@ -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();

View File

@ -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

View File

@ -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};

View File

@ -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

View File

@ -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++)
{

View File

@ -77,15 +77,24 @@ 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)
{
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_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 :

View File

@ -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 = {};

View File

@ -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;

View File

@ -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);
}

View File

@ -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)

View File

@ -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
};

View File

@ -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

View File

@ -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

View File

@ -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;
};

View File

@ -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)

View File

@ -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,9 +1236,9 @@ 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) {
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;
@ -1244,7 +1247,7 @@ void ShaderCache::QueueUberShaderPipelines()
config.rasterization_state = RenderState::GetCullBackFaceRasterizationState(
static_cast<PrimitiveType>(gs_uid.GetUidData()->primitive_type));
config.depth_state = RenderState::GetNoDepthTestingDepthState();
config.blending_state = RenderState::GetNoBlendingBlendState();
config.blending_state = blend;
if (ps_uid.GetUidData()->uint_output)
{
// uint_output is only ever enabled when logic ops are enabled.
@ -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);
}
}
});
});
});

View File

@ -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,

View File

@ -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