mirror of
https://github.com/PCSX2/pcsx2.git
synced 2026-01-31 01:15:24 +01:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
328275cd45 | ||
|
|
a4f1431bcc | ||
|
|
473df8dad4 | ||
|
|
042959958e | ||
|
|
cd4de28b9e | ||
|
|
24a87c3fee | ||
|
|
17567b960f | ||
|
|
7a3d22ecdf | ||
|
|
7e5016fdab | ||
|
|
47606400fa | ||
|
|
d6076a6107 | ||
|
|
95c57462cc | ||
|
|
48a1ec3531 | ||
|
|
9da3bccca2 | ||
|
|
a1a92920b2 | ||
|
|
b6b775e44e | ||
|
|
5ea46ac076 | ||
|
|
ab008bf5d0 | ||
|
|
54782cbf70 | ||
|
|
3c7cff99f4 | ||
|
|
f326e8775f | ||
|
|
a2a711b1b3 | ||
|
|
dfb857b68f | ||
|
|
ad64d88e7b |
@@ -12493,7 +12493,7 @@ SLED-51211:
|
||||
gsHWFixes:
|
||||
gpuTargetCLUT: 1 # Fixes bloom and sun rendering in front of everything.
|
||||
autoFlush: 1 # Fixes bloom and sun rendering in front of everything.
|
||||
halfPixelOffset: 4 # Aligns bloom effect.
|
||||
halfPixelOffset: 2 # Aligns bloom effect.
|
||||
bilinearUpscale: 2 # Reduces color banding of the sun glare.
|
||||
nativeScaling: 2 # Fixes post lighting.
|
||||
roundModes:
|
||||
@@ -12581,6 +12581,7 @@ SLED-51902:
|
||||
halfPixelOffset: 3 # Fixes double image.
|
||||
gpuTargetCLUT: 1 # Fixes sun penetrating buildings.
|
||||
autoFlush: 1 # Fixes sun occlusion.
|
||||
bilinearUpscale: 2 # Fixes sun glare textures to behave like native.
|
||||
SLED-51921:
|
||||
name: "Final Fantasy X-2 [Demo]"
|
||||
region: "PAL-Unk"
|
||||
@@ -15579,7 +15580,7 @@ SLES-51044:
|
||||
gsHWFixes:
|
||||
gpuTargetCLUT: 1 # Fixes bloom and sun rendering in front of everything.
|
||||
autoFlush: 1 # Fixes bloom and sun rendering in front of everything.
|
||||
halfPixelOffset: 4 # Aligns bloom effect.
|
||||
halfPixelOffset: 2 # Aligns bloom effect.
|
||||
bilinearUpscale: 2 # Reduces color banding of the sun glare.
|
||||
nativeScaling: 2 # Fixes post lighting.
|
||||
roundModes:
|
||||
@@ -17213,6 +17214,7 @@ SLES-51753:
|
||||
halfPixelOffset: 3 # Fixes double image.
|
||||
gpuTargetCLUT: 1 # Fixes sun penetrating buildings.
|
||||
autoFlush: 1 # Fixes sun occlusion.
|
||||
bilinearUpscale: 2 # Fixes sun glare textures to behave like native.
|
||||
SLES-51754:
|
||||
name: "True Crime - Streets of L.A."
|
||||
region: "PAL-M5"
|
||||
@@ -17222,6 +17224,7 @@ SLES-51754:
|
||||
halfPixelOffset: 3 # Fixes double image.
|
||||
gpuTargetCLUT: 1 # Fixes sun penetrating buildings.
|
||||
autoFlush: 1 # Fixes sun occlusion.
|
||||
bilinearUpscale: 2 # Fixes sun glare textures to behave like native.
|
||||
SLES-51755:
|
||||
name: "Disney/Pixar Finding Nemo"
|
||||
region: "PAL-E"
|
||||
@@ -20431,7 +20434,7 @@ SLES-52968:
|
||||
gsHWFixes:
|
||||
gpuTargetCLUT: 1 # Fixes bloom and sun rendering in front of everything.
|
||||
autoFlush: 1 # Fixes bloom and sun rendering in front of everything.
|
||||
halfPixelOffset: 4 # Aligns bloom effect.
|
||||
halfPixelOffset: 2 # Aligns bloom effect.
|
||||
bilinearUpscale: 2 # Reduces color banding of the sun glare.
|
||||
nativeScaling: 2 # Fixes post lighting.
|
||||
roundModes:
|
||||
@@ -28945,7 +28948,7 @@ SLKA-25039:
|
||||
gsHWFixes:
|
||||
gpuTargetCLUT: 1 # Fixes bloom and sun rendering in front of everything.
|
||||
autoFlush: 1 # Fixes bloom and sun rendering in front of everything.
|
||||
halfPixelOffset: 4 # Aligns bloom effect.
|
||||
halfPixelOffset: 2 # Aligns bloom effect.
|
||||
bilinearUpscale: 2 # Reduces color banding of the sun glare.
|
||||
nativeScaling: 2 # Fixes post lighting.
|
||||
roundModes:
|
||||
@@ -40823,6 +40826,7 @@ SLPM-65729:
|
||||
halfPixelOffset: 3 # Fixes double image.
|
||||
gpuTargetCLUT: 1 # Fixes sun penetrating buildings.
|
||||
autoFlush: 1 # Fixes sun occlusion.
|
||||
bilinearUpscale: 2 # Fixes sun glare textures to behave like native.
|
||||
SLPM-65730:
|
||||
name: "ロックマンX8"
|
||||
name-sort: "ろっくまんえっくす8"
|
||||
@@ -42956,6 +42960,7 @@ SLPM-66098:
|
||||
halfPixelOffset: 3 # Fixes double image.
|
||||
gpuTargetCLUT: 1 # Fixes sun penetrating buildings.
|
||||
autoFlush: 1 # Fixes sun occlusion.
|
||||
bilinearUpscale: 2 # Fixes sun glare textures to behave like native.
|
||||
SLPM-66099:
|
||||
name: "Harukanaru Toki no Naka de 3 - Izayoiki [Premium Box-Triple Pack]"
|
||||
region: "NTSC-J"
|
||||
@@ -53676,7 +53681,7 @@ SLPS-25351:
|
||||
gsHWFixes:
|
||||
gpuTargetCLUT: 1 # Fixes bloom and sun rendering in front of everything.
|
||||
autoFlush: 1 # Fixes bloom and sun rendering in front of everything.
|
||||
halfPixelOffset: 4 # Aligns bloom effect.
|
||||
halfPixelOffset: 2 # Aligns bloom effect.
|
||||
bilinearUpscale: 2 # Reduces color banding of the sun glare.
|
||||
nativeScaling: 2 # Fixes post lighting.
|
||||
roundModes:
|
||||
@@ -60437,7 +60442,7 @@ SLUS-20497:
|
||||
gsHWFixes:
|
||||
gpuTargetCLUT: 1 # Fixes bloom and sun rendering in front of everything.
|
||||
autoFlush: 1 # Fixes bloom and sun rendering in front of everything.
|
||||
halfPixelOffset: 4 # Aligns bloom effect.
|
||||
halfPixelOffset: 2 # Aligns bloom effect.
|
||||
bilinearUpscale: 2 # Reduces color banding of the sun glare.
|
||||
nativeScaling: 2 # Fixes post lighting.
|
||||
roundModes:
|
||||
@@ -60706,6 +60711,7 @@ SLUS-20550:
|
||||
halfPixelOffset: 3 # Fixes double image.
|
||||
gpuTargetCLUT: 1 # Fixes sun penetrating buildings.
|
||||
autoFlush: 1 # Fixes sun occlusion.
|
||||
bilinearUpscale: 2 # Fixes sun glare textures to behave like native.
|
||||
SLUS-20552:
|
||||
name: "Grand Theft Auto - Vice City"
|
||||
region: "NTSC-U"
|
||||
|
||||
@@ -23,6 +23,7 @@ if(UNIX AND NOT APPLE)
|
||||
option(ENABLE_SETCAP "Enable networking capability for DEV9" OFF)
|
||||
option(X11_API "Enable X11 support" ON)
|
||||
option(WAYLAND_API "Enable Wayland support" ON)
|
||||
option(USE_BACKTRACE "Enable libbacktrace support" ON)
|
||||
endif()
|
||||
|
||||
if(UNIX)
|
||||
|
||||
@@ -65,7 +65,10 @@ else()
|
||||
find_package(Wayland REQUIRED Egl)
|
||||
endif()
|
||||
|
||||
find_package(Libbacktrace REQUIRED)
|
||||
if(USE_BACKTRACE)
|
||||
find_package(Libbacktrace REQUIRED)
|
||||
endif()
|
||||
|
||||
find_package(PkgConfig REQUIRED)
|
||||
pkg_check_modules(DBUS REQUIRED dbus-1)
|
||||
endif()
|
||||
|
||||
@@ -167,10 +167,16 @@ else()
|
||||
)
|
||||
target_link_libraries(common PRIVATE
|
||||
${DBUS_LINK_LIBRARIES}
|
||||
libbacktrace::libbacktrace
|
||||
X11::X11
|
||||
X11::Xrandr
|
||||
)
|
||||
if(USE_BACKTRACE)
|
||||
target_compile_definitions(common PRIVATE "HAS_LIBBACKTRACE=1")
|
||||
target_link_libraries(common PRIVATE libbacktrace::libbacktrace)
|
||||
endif()
|
||||
if(${CMAKE_SYSTEM_NAME} STREQUAL "FreeBSD")
|
||||
target_link_libraries(common PRIVATE cpuinfo)
|
||||
endif()
|
||||
endif()
|
||||
|
||||
set_source_files_properties(PrecompiledHeader.cpp PROPERTIES HEADER_FILE_ONLY TRUE)
|
||||
|
||||
@@ -176,7 +176,7 @@ void CrashHandler::WriteDumpForCaller()
|
||||
WriteMinidumpAndCallstack(nullptr);
|
||||
}
|
||||
|
||||
#elif !defined(__APPLE__)
|
||||
#elif !defined(__APPLE__) && defined(HAS_LIBBACKTRACE)
|
||||
|
||||
#include "FileSystem.h"
|
||||
|
||||
@@ -377,4 +377,4 @@ void CrashHandler::CrashSignalHandler(int signal, siginfo_t* siginfo, void* ctx)
|
||||
std::abort();
|
||||
}
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -19,6 +19,10 @@
|
||||
|
||||
#include "fmt/core.h"
|
||||
|
||||
#if defined(__FreeBSD__)
|
||||
#include "cpuinfo.h"
|
||||
#endif
|
||||
|
||||
// FreeBSD does not have MAP_FIXED_NOREPLACE, but does have MAP_EXCL.
|
||||
// MAP_FIXED combined with MAP_EXCL behaves like MAP_FIXED_NOREPLACE.
|
||||
#if defined(__FreeBSD__) && !defined(MAP_FIXED_NOREPLACE)
|
||||
@@ -142,6 +146,22 @@ size_t HostSys::GetRuntimePageSize()
|
||||
|
||||
size_t HostSys::GetRuntimeCacheLineSize()
|
||||
{
|
||||
#if defined(__FreeBSD__)
|
||||
if (!cpuinfo_initialize())
|
||||
return 0;
|
||||
|
||||
u32 max_line_size = 0;
|
||||
for (u32 i = 0; i < cpuinfo_get_processors_count(); i++)
|
||||
{
|
||||
const u32 l1i = cpuinfo_get_processor(i)->cache.l1i->line_size;
|
||||
const u32 l1d = cpuinfo_get_processor(i)->cache.l1d->line_size;
|
||||
const u32 res = std::max<u32>(l1i, l1d);
|
||||
|
||||
max_line_size = std::max<u32>(max_line_size, res);
|
||||
}
|
||||
|
||||
return static_cast<size_t>(max_line_size);
|
||||
#else
|
||||
int l1i = sysconf(_SC_LEVEL1_DCACHE_LINESIZE);
|
||||
int l1d = sysconf(_SC_LEVEL1_ICACHE_LINESIZE);
|
||||
int res = (l1i > l1d) ? l1i : l1d;
|
||||
@@ -160,6 +180,7 @@ size_t HostSys::GetRuntimeCacheLineSize()
|
||||
}
|
||||
|
||||
return (res > 0) ? static_cast<size_t>(res) : 0;
|
||||
#endif
|
||||
}
|
||||
|
||||
SharedMemoryMappingArea::SharedMemoryMappingArea(u8* base_ptr, size_t size, size_t num_pages)
|
||||
|
||||
@@ -66,24 +66,23 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
|
||||
const u32 currentRowAddress = startAddress + (i * 0x10);
|
||||
s32 valX = valuexAxis;
|
||||
segmentXAxis[0] = valX;
|
||||
u32 currentSegmentAddress = currentRowAddress;
|
||||
for (int j = 0; j < 16 / (s32)displayType; j++)
|
||||
for (int j = 0; j < 16 / static_cast<s32>(displayType); j++)
|
||||
{
|
||||
valX += charWidth;
|
||||
const u32 thisSegmentsStart = currentRowAddress + (j * (s32)displayType);
|
||||
const u32 thisSegmentsStart = currentRowAddress + (j * static_cast<s32>(displayType));
|
||||
|
||||
segmentXAxis[j] = valX;
|
||||
|
||||
bool penDefault = false;
|
||||
if ((selectedAddress & ~0xF) == currentRowAddress)
|
||||
{
|
||||
if (selectedAddress >= thisSegmentsStart && selectedAddress < (thisSegmentsStart + (s32)displayType))
|
||||
if (selectedAddress >= thisSegmentsStart && selectedAddress < (thisSegmentsStart + static_cast<s32>(displayType)))
|
||||
{ // If the current byte and row we are drawing is selected
|
||||
if (!selectedText)
|
||||
{
|
||||
s32 charsIntoSegment = ((selectedAddress - thisSegmentsStart) * 2) + ((selectedNibbleHI ? 0 : 1) ^ littleEndian);
|
||||
if (littleEndian)
|
||||
charsIntoSegment = ((s32)displayType * 2) - charsIntoSegment - 1;
|
||||
charsIntoSegment = (static_cast<s32>(displayType) * 2) - charsIntoSegment - 1;
|
||||
painter.setPen(QColor::fromRgb(205, 165, 0)); // SELECTED NIBBLE LINE COLOUR
|
||||
const QPoint lineStart(valX + (charsIntoSegment * charWidth) + 1, y + (rowHeight * i));
|
||||
painter.drawLine(lineStart, lineStart + QPoint(charWidth - 3, 0));
|
||||
@@ -138,7 +137,7 @@ void MemoryViewTable::DrawTable(QPainter& painter, const QPalette& palette, s32
|
||||
break;
|
||||
}
|
||||
}
|
||||
valX += charWidth * 2 * (s32)displayType;
|
||||
valX += charWidth * 2 * static_cast<s32>(displayType);
|
||||
}
|
||||
|
||||
// valX is our new X position after the hex values
|
||||
@@ -185,7 +184,7 @@ void MemoryViewTable::SelectAt(QPoint pos)
|
||||
// The user clicked before the first segment
|
||||
selectedText = false;
|
||||
if (littleEndian)
|
||||
selectedAddress += (s32)displayType - 1;
|
||||
selectedAddress += static_cast<s32>(displayType) - 1;
|
||||
selectedNibbleHI = true;
|
||||
}
|
||||
else if (x > valuexAxis && x < textXAxis)
|
||||
@@ -194,12 +193,12 @@ void MemoryViewTable::SelectAt(QPoint pos)
|
||||
// The user clicked inside of the hexadecimal area
|
||||
for (s32 i = 0; i < 16; i++)
|
||||
{
|
||||
if (i == ((16 / (s32)displayType) - 1) || (x >= segmentXAxis[i] && x < (segmentXAxis[i + 1])))
|
||||
if (i == ((16 / static_cast<s32>(displayType)) - 1) || (x >= segmentXAxis[i] && x < (segmentXAxis[i + 1])))
|
||||
{
|
||||
u32 indexInSegment = (x - segmentXAxis[i]) / nibbleWidth;
|
||||
if (littleEndian)
|
||||
indexInSegment = ((s32)displayType * 2) - indexInSegment - 1;
|
||||
selectedAddress = selectedAddress + i * (s32)displayType + (indexInSegment / 2);
|
||||
indexInSegment = (static_cast<s32>(displayType) * 2) - indexInSegment - 1;
|
||||
selectedAddress = selectedAddress + i * static_cast<s32>(displayType) + (indexInSegment / 2);
|
||||
selectedNibbleHI = littleEndian ? indexInSegment & 1 : !(indexInSegment & 1);
|
||||
break;
|
||||
}
|
||||
@@ -222,7 +221,7 @@ u128 MemoryViewTable::GetSelectedSegment()
|
||||
val.lo = m_cpu->read8(selectedAddress);
|
||||
break;
|
||||
case MemoryViewType::BYTEHW:
|
||||
val.lo = convertEndian((u16)m_cpu->read16(selectedAddress & ~1));
|
||||
val.lo = convertEndian(static_cast<u16>(m_cpu->read16(selectedAddress & ~1)));
|
||||
break;
|
||||
case MemoryViewType::WORD:
|
||||
val.lo = convertEndian(m_cpu->read32(selectedAddress & ~3));
|
||||
@@ -276,8 +275,8 @@ u32 MemoryViewTable::nextAddress(u32 addr)
|
||||
}
|
||||
else
|
||||
{
|
||||
if (selectedAddress % (s32)displayType == 0)
|
||||
return addr + ((s32)displayType * 2 - 1);
|
||||
if (selectedAddress % static_cast<s32>(displayType) == 0)
|
||||
return addr + (static_cast<s32>(displayType) * 2 - 1);
|
||||
else
|
||||
return addr - 1;
|
||||
}
|
||||
@@ -292,8 +291,8 @@ u32 MemoryViewTable::prevAddress(u32 addr)
|
||||
else
|
||||
{
|
||||
// It works
|
||||
if ((addr & ((s32)displayType - 1)) == ((s32)displayType - 1))
|
||||
return addr - ((s32)displayType * 2 - 1);
|
||||
if ((addr & (static_cast<u32>(displayType) - 1)) == (static_cast<u32>(displayType) - 1))
|
||||
return addr - (static_cast<s32>(displayType) * 2 - 1);
|
||||
else
|
||||
return selectedAddress + 1;
|
||||
}
|
||||
@@ -310,8 +309,8 @@ void MemoryViewTable::ForwardSelection()
|
||||
{
|
||||
if ((selectedNibbleHI = !selectedNibbleHI))
|
||||
{
|
||||
if (selectedAddress % (s32)displayType == 0)
|
||||
UpdateSelectedAddress(selectedAddress + ((s32)displayType * 2 - 1));
|
||||
if (selectedAddress % static_cast<s32>(displayType) == 0)
|
||||
UpdateSelectedAddress(selectedAddress + (static_cast<s32>(displayType) * 2 - 1));
|
||||
else
|
||||
UpdateSelectedAddress(selectedAddress - 1);
|
||||
}
|
||||
@@ -330,8 +329,8 @@ void MemoryViewTable::BackwardSelection()
|
||||
if (!(selectedNibbleHI = !selectedNibbleHI))
|
||||
{
|
||||
// It works
|
||||
if ((selectedAddress & ((s32)displayType - 1)) == ((s32)displayType - 1))
|
||||
UpdateSelectedAddress(selectedAddress - ((s32)displayType * 2 - 1));
|
||||
if ((selectedAddress & (static_cast<u32>(displayType) - 1)) == (static_cast<u32>(displayType) - 1))
|
||||
UpdateSelectedAddress(selectedAddress - (static_cast<s32>(displayType) * 2 - 1));
|
||||
else
|
||||
UpdateSelectedAddress(selectedAddress + 1);
|
||||
}
|
||||
@@ -389,7 +388,7 @@ bool MemoryViewTable::KeyPress(int key, QChar keychar)
|
||||
if (keyCharIsText)
|
||||
{
|
||||
// Check if key pressed is hex before insertion (QString conversion fails otherwise)
|
||||
const u8 keyPressed = (u8)QString(QChar(key)).toInt(&pressHandled, 16);
|
||||
const u8 keyPressed = static_cast<u8>(QString(QChar(key)).toInt(&pressHandled, 16));
|
||||
if (pressHandled)
|
||||
{
|
||||
InsertIntoSelectedHexView(keyPressed);
|
||||
|
||||
@@ -256,8 +256,6 @@ Qt::ItemFlags BreakpointModel::flags(const QModelIndex& index) const
|
||||
{
|
||||
volatile const int row = index.row();
|
||||
|
||||
const bool is_breakpoint = std::holds_alternative<BreakPoint>(m_breakpoints.at(row));
|
||||
|
||||
switch (index.column())
|
||||
{
|
||||
case BreakpointColumns::CONDITION:
|
||||
|
||||
@@ -851,16 +851,16 @@ void MainWindow::restoreStateFromConfig()
|
||||
|
||||
void MainWindow::updateEmulationActions(bool starting, bool running, bool stopping)
|
||||
{
|
||||
const bool starting_or_running = starting || running;
|
||||
const bool starting_or_running_or_stopping = starting || running || stopping;
|
||||
|
||||
m_ui.actionStartFile->setDisabled(starting_or_running || stopping);
|
||||
m_ui.actionStartDisc->setDisabled(starting_or_running || stopping);
|
||||
m_ui.actionStartBios->setDisabled(starting_or_running || stopping);
|
||||
m_ui.actionToolbarStartFile->setDisabled(starting_or_running || stopping);
|
||||
m_ui.actionToolbarStartDisc->setDisabled(starting_or_running || stopping);
|
||||
m_ui.actionToolbarStartBios->setDisabled(starting_or_running || stopping);
|
||||
m_ui.actionStartFullscreenUI->setDisabled(starting_or_running || stopping);
|
||||
m_ui.actionToolbarStartFullscreenUI->setDisabled(starting_or_running || stopping);
|
||||
m_ui.actionStartFile->setDisabled(starting_or_running_or_stopping);
|
||||
m_ui.actionStartDisc->setDisabled(starting_or_running_or_stopping);
|
||||
m_ui.actionStartBios->setDisabled(starting_or_running_or_stopping);
|
||||
m_ui.actionToolbarStartFile->setDisabled(starting_or_running_or_stopping);
|
||||
m_ui.actionToolbarStartDisc->setDisabled(starting_or_running_or_stopping);
|
||||
m_ui.actionToolbarStartBios->setDisabled(starting_or_running_or_stopping);
|
||||
m_ui.actionStartFullscreenUI->setDisabled(starting_or_running_or_stopping);
|
||||
m_ui.actionToolbarStartFullscreenUI->setDisabled(starting_or_running_or_stopping);
|
||||
|
||||
m_ui.actionPowerOff->setEnabled(running);
|
||||
m_ui.actionPowerOffWithoutSaving->setEnabled(running);
|
||||
@@ -869,6 +869,7 @@ void MainWindow::updateEmulationActions(bool starting, bool running, bool stoppi
|
||||
m_ui.actionScreenshot->setEnabled(running);
|
||||
m_ui.menuChangeDisc->setEnabled(running);
|
||||
m_ui.menuSaveState->setEnabled(running);
|
||||
m_ui.actionSaveGSDump->setEnabled(running);
|
||||
|
||||
m_ui.actionToolbarPowerOff->setEnabled(running);
|
||||
m_ui.actionToolbarReset->setEnabled(running);
|
||||
@@ -902,8 +903,8 @@ void MainWindow::updateEmulationActions(bool starting, bool running, bool stoppi
|
||||
}
|
||||
|
||||
// scanning needs to be disabled while running
|
||||
m_ui.actionScanForNewGames->setDisabled(starting_or_running || stopping);
|
||||
m_ui.actionRescanAllGames->setDisabled(starting_or_running || stopping);
|
||||
m_ui.actionScanForNewGames->setDisabled(starting_or_running_or_stopping);
|
||||
m_ui.actionRescanAllGames->setDisabled(starting_or_running_or_stopping);
|
||||
}
|
||||
|
||||
void MainWindow::updateDisplayRelatedActions(bool has_surface, bool render_to_main, bool fullscreen)
|
||||
@@ -1053,7 +1054,7 @@ bool MainWindow::shouldHideMouseCursor() const
|
||||
bool MainWindow::shouldHideMainWindow() const
|
||||
{
|
||||
// NOTE: We can't use isRenderingToMain() here, because this happens post-fullscreen-switch.
|
||||
return Host::GetBoolSettingValue("UI", "HideMainWindowWhenRunning", false) ||
|
||||
return (Host::GetBoolSettingValue("UI", "HideMainWindowWhenRunning", false) && !g_emu_thread->shouldRenderToMain()) ||
|
||||
(g_emu_thread->shouldRenderToMain() && (isRenderingFullscreen() || m_is_temporarily_windowed)) ||
|
||||
QtHost::InNoGUIMode();
|
||||
}
|
||||
|
||||
@@ -124,6 +124,7 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowSettings, "EmuCore/GS", "OsdShowSettings", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowInputs, "EmuCore/GS", "OsdShowInputs", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowFrameTimes, "EmuCore/GS", "OsdShowFrameTimes", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.osdShowVersion, "EmuCore/GS", "OsdShowVersion", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.warnAboutUnsafeSettings, "EmuCore", "WarnAboutUnsafeSettings", true);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.fxaa, "EmuCore/GS", "fxaa", false);
|
||||
SettingWidgetBinder::BindWidgetToBoolSetting(sif, m_ui.shadeBoost, "EmuCore/GS", "ShadeBoost", false);
|
||||
@@ -718,8 +719,11 @@ GraphicsSettingsWidget::GraphicsSettingsWidget(SettingsWindow* dialog, QWidget*
|
||||
dialog->registerWidgetHelp(m_ui.osdShowInputs, tr("Show Inputs"), tr("Unchecked"),
|
||||
tr("Shows the current controller state of the system in the bottom-left corner of the display."));
|
||||
|
||||
dialog->registerWidgetHelp(
|
||||
m_ui.osdShowFrameTimes, tr("Show Frame Times"), tr("Unchecked"), tr("Displays a graph showing the average frametimes."));
|
||||
dialog->registerWidgetHelp(m_ui.osdShowFrameTimes, tr("Show Frame Times"), tr("Unchecked"),
|
||||
tr("Displays a graph showing the average frametimes."));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.osdShowVersion, tr("Show PCSX2 Version"), tr("Unchecked"),
|
||||
tr("Shows the current PCSX2 version on the top-right corner of the display"));
|
||||
|
||||
dialog->registerWidgetHelp(m_ui.warnAboutUnsafeSettings, tr("Warn About Unsafe Settings"), tr("Checked"),
|
||||
tr("Displays warnings when settings are enabled which may break games."));
|
||||
|
||||
@@ -1610,59 +1610,17 @@
|
||||
</item>
|
||||
<item row="1" column="0" colspan="2">
|
||||
<layout class="QGridLayout" name="gridLayout_6">
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="osdShowIndicators">
|
||||
<property name="text">
|
||||
<string>Show Indicators</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="1">
|
||||
<widget class="QCheckBox" name="osdShowResolution">
|
||||
<property name="text">
|
||||
<string>Show Resolution</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="osdShowInputs">
|
||||
<property name="text">
|
||||
<string>Show Inputs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="osdShowGPU">
|
||||
<property name="text">
|
||||
<string>Show GPU Usage</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="osdShowSettings">
|
||||
<property name="text">
|
||||
<string>Show Settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="osdShowFPS">
|
||||
<property name="text">
|
||||
<string>Show FPS</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="osdShowMessages">
|
||||
<item row="1" column="0">
|
||||
<widget class="QCheckBox" name="osdShowVersion">
|
||||
<property name="text">
|
||||
<string>Show OSD Messages</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="osdShowGSStats">
|
||||
<property name="text">
|
||||
<string>Show Statistics</string>
|
||||
<string>Show PCSX2 Version</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
@@ -1673,27 +1631,76 @@
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="osdShowSpeed">
|
||||
<item row="3" column="1">
|
||||
<widget class="QCheckBox" name="osdShowIndicators">
|
||||
<property name="text">
|
||||
<string>Show Speed Percentages</string>
|
||||
<string>Show Indicators</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="1">
|
||||
<item row="0" column="0">
|
||||
<widget class="QCheckBox" name="osdShowMessages">
|
||||
<property name="text">
|
||||
<string>Show OSD Messages</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="7" column="0">
|
||||
<widget class="QCheckBox" name="warnAboutUnsafeSettings">
|
||||
<property name="text">
|
||||
<string>Warn About Unsafe Settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="5" column="0">
|
||||
<item row="2" column="1">
|
||||
<widget class="QCheckBox" name="osdShowGPU">
|
||||
<property name="text">
|
||||
<string>Show GPU Usage</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="0" column="1">
|
||||
<widget class="QCheckBox" name="osdShowResolution">
|
||||
<property name="text">
|
||||
<string>Show Resolution</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="1">
|
||||
<widget class="QCheckBox" name="osdShowFrameTimes">
|
||||
<property name="text">
|
||||
<string>Show Frame Times</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="1">
|
||||
<widget class="QCheckBox" name="osdShowGSStats">
|
||||
<property name="text">
|
||||
<string>Show Statistics</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="3" column="0">
|
||||
<widget class="QCheckBox" name="osdShowSpeed">
|
||||
<property name="text">
|
||||
<string>Show Speed Percentages</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="6" column="0">
|
||||
<widget class="QCheckBox" name="osdShowInputs">
|
||||
<property name="text">
|
||||
<string>Show Inputs</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
<item row="4" column="0">
|
||||
<widget class="QCheckBox" name="osdShowSettings">
|
||||
<property name="text">
|
||||
<string>Show Settings</string>
|
||||
</property>
|
||||
</widget>
|
||||
</item>
|
||||
</layout>
|
||||
</item>
|
||||
</layout>
|
||||
|
||||
File diff suppressed because it is too large
Load Diff
@@ -621,6 +621,7 @@ struct Pcsx2Config
|
||||
OsdShowSettings : 1,
|
||||
OsdShowInputs : 1,
|
||||
OsdShowFrameTimes : 1,
|
||||
OsdShowVersion : 1,
|
||||
HWSpinGPUForReadbacks : 1,
|
||||
HWSpinCPUForReadbacks : 1,
|
||||
GPUPaletteConversion : 1,
|
||||
|
||||
@@ -96,10 +96,10 @@ namespace PacketReader::IP
|
||||
{
|
||||
//If buffer & data point to the same location
|
||||
//Then no copy is needed
|
||||
if (data == buffer)
|
||||
if (data == &buffer[*offset])
|
||||
return;
|
||||
|
||||
memcpy(buffer, data, length);
|
||||
memcpy(&buffer[*offset], data, length);
|
||||
*offset += length;
|
||||
}
|
||||
virtual IP_Payload* Clone() const
|
||||
|
||||
@@ -15,8 +15,11 @@
|
||||
#endif
|
||||
|
||||
#include <algorithm>
|
||||
#include <bit>
|
||||
#include <thread>
|
||||
#include <errno.h>
|
||||
#include <sys/types.h>
|
||||
#include <sys/ioctl.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netinet/in.h>
|
||||
#include <netinet/ip.h>
|
||||
@@ -35,36 +38,38 @@ using namespace PacketReader::IP::ICMP;
|
||||
|
||||
using namespace std::chrono_literals;
|
||||
|
||||
/* Ping is kindof annoying to do crossplatform
|
||||
All platforms restrict raw sockets
|
||||
|
||||
Windows provides an api for ICMP
|
||||
ICMP_ECHO_REPLY should always be used, ignore ICMP_ECHO_REPLY32
|
||||
IP_OPTION_INFORMATION should always be used, ignore IP_OPTION_INFORMATION32
|
||||
|
||||
Linux
|
||||
We have access to raw sockets via CAP_NET_RAW (for pcap)
|
||||
However we may be missing that cap on some builds
|
||||
Linux has socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP), used similar to raw sockets but for ICMP only
|
||||
Auto filters responses
|
||||
Requires net.ipv4.ping_group_range sysctl, default off on alot of distros
|
||||
Timeouts reported via sock_extended_err control messages (with IP_RECVERR socket option set)
|
||||
|
||||
Mac
|
||||
Raw sockets restricted
|
||||
Mac has socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP)
|
||||
No restriction to using it
|
||||
Implementation differs, is more versatile than linux
|
||||
Does not auto filter responses
|
||||
Timeouts reported as a normal packet
|
||||
|
||||
FreeBSD
|
||||
Raw sockets restricted
|
||||
No unprivilaged ICMP sockets
|
||||
Timeouts reported as a normal packet??
|
||||
|
||||
Ping cli
|
||||
Present for all platforms, but command args differ
|
||||
/*
|
||||
* Ping is kindof annoying to do crossplatform
|
||||
* All platforms restrict raw sockets
|
||||
*
|
||||
* Windows provides an api for ICMP
|
||||
* ICMP_ECHO_REPLY should always be used, ignore ICMP_ECHO_REPLY32
|
||||
* IP_OPTION_INFORMATION should always be used, ignore IP_OPTION_INFORMATION32
|
||||
*
|
||||
* Linux
|
||||
* We have access to raw sockets via CAP_NET_RAW (for pcap)
|
||||
* However we may be missing that cap on some builds
|
||||
* Also hava socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP), used similarly to raw sockets, but for ICMP only
|
||||
* Auto filters responses
|
||||
* Requires net.ipv4.ping_group_range sysctl, default off on a lot of distros
|
||||
* Timeouts reported via sock_extended_err control messages (with IP_RECVERR socket option set)
|
||||
*
|
||||
* Mac
|
||||
* Raw sockets restricted
|
||||
* Mac has socket(PF_INET, SOCK_DGRAM, IPPROTO_ICMP)
|
||||
* No restriction to using it with ICMP_ECHO
|
||||
* Implementation differs, is more versatile than linux
|
||||
* Does not auto filter responses
|
||||
* Timeouts reported as a normal packet
|
||||
*
|
||||
* FreeBSD
|
||||
* Raw sockets restricted
|
||||
* No unprivilaged ICMP sockets
|
||||
* Timeouts reported as a normal packet??
|
||||
*
|
||||
* Ping cli
|
||||
* Present for all platforms, but command args differ
|
||||
* Not used here
|
||||
*/
|
||||
|
||||
namespace Sessions
|
||||
@@ -95,29 +100,36 @@ namespace Sessions
|
||||
return;
|
||||
}
|
||||
|
||||
//Allocate return buffer
|
||||
//Documentation says + 8 to allow for an ICMP error message
|
||||
//In testing, ICMP_ECHO_REPLY structure itself was returned with data set to null
|
||||
/*
|
||||
* Allocate response buffer
|
||||
* Documentation says + 8 to allow for an ICMP error message
|
||||
* In testing, ICMP_ECHO_REPLY structure itself was returned with data set to null
|
||||
*/
|
||||
icmpResponseBufferLen = sizeof(ICMP_ECHO_REPLY) + requestSize + 8;
|
||||
icmpResponseBuffer = std::make_unique<u8[]>(icmpResponseBufferLen);
|
||||
icmpResponseBuffer = std::make_unique<std::byte[]>(icmpResponseBufferLen);
|
||||
#elif defined(__POSIX__)
|
||||
{
|
||||
/*
|
||||
* Allocate response buffer
|
||||
* Size needed depends on which socket protocol (ICMP or raw) we use aswell as os
|
||||
*/
|
||||
switch (icmpConnectionKind)
|
||||
{
|
||||
//Two different methods for raw/icmp sockets bettween the unix OSes
|
||||
//Play it safe and only enable when we know which of the two methods we use
|
||||
// Two different methods for raw/icmp sockets between the Unix OSes
|
||||
// Play it safe and only enable when we know which of the two methods we use
|
||||
#if defined(ICMP_SOCKETS_LINUX) || defined(ICMP_SOCKETS_BSD)
|
||||
case (PingType::ICMP):
|
||||
icmpSocket = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
|
||||
if (icmpSocket != -1)
|
||||
{
|
||||
#if defined(ICMP_SOCKETS_LINUX)
|
||||
//Space for ICMP header, as MSG_ERRQUEUE returns what we sent
|
||||
//An extra +8 required sometimes, for some reason?
|
||||
// Only need space for ICMP header, as MSG_ERRQUEUE returns data we sent
|
||||
// Testing found an extra + 8 was required sometimes, for some reason?
|
||||
icmpResponseBufferLen = 8 + requestSize + 8;
|
||||
#elif defined(ICMP_SOCKETS_BSD)
|
||||
//Returned IP Header, ICMP Header & either data or failed ICMP packet
|
||||
icmpResponseBufferLen = 20 + 8 + std::max(20 + 8, requestSize);
|
||||
// Returned IP Header, ICMP Header & either data or failed ICMP packet
|
||||
// Sometimes get full packet in ICMP error response
|
||||
icmpResponseBufferLen = 20 + 8 + (20 + 8 + requestSize);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
@@ -132,16 +144,17 @@ namespace Sessions
|
||||
if (icmpSocket != -1)
|
||||
{
|
||||
#if defined(ICMP_SOCKETS_LINUX)
|
||||
//We get packet + header
|
||||
// We get IP packet + ICMP header
|
||||
icmpResponseBufferLen = 20 + 8 + requestSize;
|
||||
#elif defined(ICMP_SOCKETS_BSD)
|
||||
//As above, but we will also directly recive error ICMP messages
|
||||
// As above, but we will also directly receive error ICMP messages
|
||||
icmpResponseBufferLen = 20 + 8 + std::max(20 + 8, requestSize);
|
||||
#endif
|
||||
break;
|
||||
}
|
||||
|
||||
DevCon.WriteLn("DEV9: ICMP: Failed To Open RAW Socket");
|
||||
|
||||
[[fallthrough]];
|
||||
#endif
|
||||
default:
|
||||
@@ -149,11 +162,11 @@ namespace Sessions
|
||||
return;
|
||||
}
|
||||
|
||||
icmpResponseBuffer = std::make_unique<u8[]>(icmpResponseBufferLen);
|
||||
icmpResponseBuffer = std::make_unique<std::byte[]>(icmpResponseBufferLen);
|
||||
#endif
|
||||
}
|
||||
|
||||
bool ICMP_Session::Ping::IsInitialised()
|
||||
bool ICMP_Session::Ping::IsInitialised() const
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return icmpFile != INVALID_HANDLE_VALUE;
|
||||
@@ -169,19 +182,29 @@ namespace Sessions
|
||||
#endif
|
||||
}
|
||||
|
||||
//Note, we can finish reading but have no data
|
||||
// Returned PingResult.data is only valid when PingResult.type is 0
|
||||
ICMP_Session::PingResult* ICMP_Session::Ping::Recv()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (WaitForSingleObject(icmpEvent, 0) == WAIT_OBJECT_0)
|
||||
{
|
||||
ResetEvent(icmpEvent);
|
||||
//Prep buffer for reasing
|
||||
[[maybe_unused]] int count = IcmpParseReplies(icmpResponseBuffer.get(), icmpResponseBufferLen);
|
||||
pxAssert(count == 1);
|
||||
ICMP_ECHO_REPLY* pingRet = (ICMP_ECHO_REPLY*)icmpResponseBuffer.get();
|
||||
|
||||
//Map status to ICMP type/code
|
||||
const int count = IcmpParseReplies(icmpResponseBuffer.get(), icmpResponseBufferLen);
|
||||
pxAssert(count <= 1);
|
||||
|
||||
// Timeout
|
||||
if (count == 0)
|
||||
{
|
||||
result.type = -2;
|
||||
result.code = 0;
|
||||
return &result;
|
||||
}
|
||||
|
||||
// Rely on implicit object creation
|
||||
const ICMP_ECHO_REPLY* pingRet = reinterpret_cast<ICMP_ECHO_REPLY*>(icmpResponseBuffer.get());
|
||||
|
||||
// Map status to ICMP type/code
|
||||
switch (pingRet->Status)
|
||||
{
|
||||
case (IP_SUCCESS):
|
||||
@@ -208,21 +231,23 @@ namespace Sessions
|
||||
result.type = 3;
|
||||
result.code = 4;
|
||||
break;
|
||||
case (IP_BAD_ROUTE): //Bad source route
|
||||
case (IP_BAD_ROUTE): // Bad source route
|
||||
result.type = 3;
|
||||
result.code = 5;
|
||||
break;
|
||||
case (IP_BAD_DESTINATION):
|
||||
//I think this could be either
|
||||
//Destination network unknown
|
||||
//or
|
||||
//Destination host unknown
|
||||
//Use host unkown
|
||||
/*
|
||||
* I think this could be mapped to either
|
||||
* Destination network unknown
|
||||
* or
|
||||
* Destination host unknown
|
||||
* Lets map to host unknown
|
||||
*/
|
||||
result.type = 3;
|
||||
result.code = 7;
|
||||
break;
|
||||
case (IP_REQ_TIMED_OUT):
|
||||
//Return nothing
|
||||
// Return nothing
|
||||
result.type = -2;
|
||||
result.code = 0;
|
||||
break;
|
||||
@@ -239,7 +264,7 @@ namespace Sessions
|
||||
result.code = 0;
|
||||
break;
|
||||
|
||||
//Unexpected Errors
|
||||
// Unexpected errors
|
||||
case (IP_BUF_TOO_SMALL):
|
||||
case (IP_NO_RESOURCES):
|
||||
case (IP_BAD_OPTION):
|
||||
@@ -255,7 +280,7 @@ namespace Sessions
|
||||
}
|
||||
|
||||
result.dataLength = pingRet->DataSize;
|
||||
result.data = (u8*)pingRet->Data;
|
||||
result.data = static_cast<u8*>(pingRet->Data);
|
||||
result.address.integer = pingRet->Address;
|
||||
|
||||
return &result;
|
||||
@@ -268,82 +293,30 @@ namespace Sessions
|
||||
case (PingType::ICMP):
|
||||
case (PingType::RAW):
|
||||
{
|
||||
int ret;
|
||||
|
||||
#if defined(ICMP_SOCKETS_BSD)
|
||||
fd_set sReady;
|
||||
fd_set sExcept;
|
||||
|
||||
timeval nowait{0};
|
||||
FD_ZERO(&sReady);
|
||||
FD_ZERO(&sExcept);
|
||||
FD_SET(icmpSocket, &sReady);
|
||||
FD_SET(icmpSocket, &sExcept);
|
||||
ret = select(icmpSocket + 1, &sReady, nullptr, &sExcept, &nowait);
|
||||
|
||||
bool hasData;
|
||||
if (ret == -1)
|
||||
{
|
||||
hasData = false;
|
||||
Console.WriteLn("DEV9: ICMP: select failed. Error Code: %d", errno);
|
||||
}
|
||||
else if (FD_ISSET(icmpSocket, &sExcept))
|
||||
{
|
||||
hasData = false;
|
||||
|
||||
int error = 0;
|
||||
|
||||
socklen_t len = sizeof(error);
|
||||
if (getsockopt(icmpSocket, SOL_SOCKET, SO_ERROR, (char*)&error, &len) < 0)
|
||||
Console.Error("DEV9: ICMP: Unkown ICMP Connection Error (getsockopt Error: %d)", errno);
|
||||
else
|
||||
Console.Error("DEV9: ICMP: Recv Error: %d", error);
|
||||
}
|
||||
else
|
||||
hasData = FD_ISSET(icmpSocket, &sReady);
|
||||
|
||||
if (hasData == false)
|
||||
{
|
||||
if (std::chrono::steady_clock::now() - icmpDeathClockStart > ICMP_TIMEOUT)
|
||||
{
|
||||
result.type = -2;
|
||||
result.code = 0;
|
||||
return &result;
|
||||
}
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
#endif
|
||||
|
||||
sockaddr endpoint{0};
|
||||
sockaddr_in endpoint{};
|
||||
|
||||
iovec iov;
|
||||
iov.iov_base = icmpResponseBuffer.get();
|
||||
iov.iov_len = icmpResponseBufferLen;
|
||||
|
||||
#if defined(ICMP_SOCKETS_LINUX)
|
||||
//Needs to hold cmsghdr + sock_extended_err + sockaddr_in
|
||||
//for ICMP error responses (total 44 bytes)
|
||||
//Unkown for other types of error
|
||||
u8 cbuff[64];
|
||||
// Needs to hold cmsghdr + sock_extended_err + sockaddr_in
|
||||
// for ICMP error responses, this is a total of 44 bytes
|
||||
// Unknown size needed for other error types
|
||||
std::byte cbuff[64]{};
|
||||
#endif
|
||||
|
||||
msghdr msg{0};
|
||||
msghdr msg{};
|
||||
msg.msg_name = &endpoint;
|
||||
msg.msg_namelen = sizeof(endpoint);
|
||||
msg.msg_iov = &iov;
|
||||
msg.msg_iovlen = 1;
|
||||
|
||||
#if defined(ICMP_SOCKETS_LINUX)
|
||||
ret = recvmsg(icmpSocket, &msg, MSG_DONTWAIT);
|
||||
#elif defined(ICMP_SOCKETS_BSD)
|
||||
ret = recvmsg(icmpSocket, &msg, 0);
|
||||
#endif
|
||||
int ret = recvmsg(icmpSocket, &msg, 0);
|
||||
|
||||
if (ret == -1)
|
||||
{
|
||||
int err = errno;
|
||||
#if defined(ICMP_SOCKETS_LINUX)
|
||||
if (err == EAGAIN || err == EWOULDBLOCK)
|
||||
{
|
||||
if (std::chrono::steady_clock::now() - icmpDeathClockStart > ICMP_TIMEOUT)
|
||||
@@ -355,14 +328,16 @@ namespace Sessions
|
||||
else
|
||||
return nullptr;
|
||||
}
|
||||
#if defined(ICMP_SOCKETS_LINUX)
|
||||
else
|
||||
{
|
||||
msg.msg_control = &cbuff;
|
||||
msg.msg_controllen = sizeof(cbuff);
|
||||
ret = recvmsg(icmpSocket, &msg, MSG_ERRQUEUE | MSG_DONTWAIT);
|
||||
ret = recvmsg(icmpSocket, &msg, MSG_ERRQUEUE);
|
||||
}
|
||||
#endif
|
||||
|
||||
if (ret == -1)
|
||||
#endif
|
||||
{
|
||||
Console.Error("DEV9: ICMP: RecvMsg Error: %d", err);
|
||||
result.type = -1;
|
||||
@@ -373,40 +348,59 @@ namespace Sessions
|
||||
|
||||
if (msg.msg_flags & MSG_TRUNC)
|
||||
Console.Error("DEV9: ICMP: RecvMsg Truncated");
|
||||
|
||||
#if defined(ICMP_SOCKETS_LINUX)
|
||||
if (msg.msg_flags & MSG_CTRUNC)
|
||||
Console.Error("DEV9: ICMP: RecvMsg Control Truncated");
|
||||
|
||||
sock_extended_err* ex_err = nullptr;
|
||||
// On Linux, ICMP errors are stored in control messages retrieved using MSG_ERRQUEUE
|
||||
sock_extended_err* exErrorPtr = nullptr;
|
||||
cmsghdr* cmsg;
|
||||
|
||||
/* Receive auxiliary data in msgh */
|
||||
// Search though control messages, taking the latest mesage
|
||||
// We should only have at most 1 message
|
||||
for (cmsg = CMSG_FIRSTHDR(&msg); cmsg != NULL; cmsg = CMSG_NXTHDR(&msg, cmsg))
|
||||
{
|
||||
if (cmsg->cmsg_level == SOL_IP && cmsg->cmsg_type == IP_RECVERR)
|
||||
{
|
||||
ex_err = (sock_extended_err*)CMSG_DATA(cmsg);
|
||||
pxAssert(!exErrorPtr);
|
||||
exErrorPtr = reinterpret_cast<sock_extended_err*>(CMSG_DATA(cmsg));
|
||||
continue;
|
||||
}
|
||||
pxAssert(false);
|
||||
}
|
||||
|
||||
if (ex_err != nullptr)
|
||||
if (exErrorPtr != nullptr)
|
||||
{
|
||||
if (ex_err->ee_origin == SO_EE_ORIGIN_ICMP)
|
||||
{
|
||||
result.type = ex_err->ee_type;
|
||||
result.code = ex_err->ee_code;
|
||||
/*
|
||||
* The pointer returned cannot be assumed to be suitably aligned for accessing arbitrary payload data types
|
||||
* So we would need to memcpy sock_extended_err
|
||||
*/
|
||||
sock_extended_err exError;
|
||||
std::memcpy(&exError, exErrorPtr, sizeof(exError));
|
||||
|
||||
sockaddr_in* sockaddr = (sockaddr_in*)SO_EE_OFFENDER(ex_err);
|
||||
result.address = *(IP_Address*)&sockaddr->sin_addr;
|
||||
// Process the error
|
||||
if (exError.ee_origin == SO_EE_ORIGIN_ICMP)
|
||||
{
|
||||
result.type = exError.ee_type;
|
||||
result.code = exError.ee_code;
|
||||
|
||||
/*
|
||||
* SO_EE_OFFENDER reads data relative to, but not necessarily included in struct sock_extended_err
|
||||
* So we need to pass the original pointer provided to us from CMSG_DATA()
|
||||
* However, the input pointer needs to be of type sock_extended_err*, hence the reinterpret_cast
|
||||
* The pointer returned may not be suitably aligned (see CMSG_DATA), so we need to memcpy
|
||||
*/
|
||||
sockaddr_in errorEndpoint;
|
||||
std::memcpy(&errorEndpoint, SO_EE_OFFENDER(exErrorPtr), sizeof(errorEndpoint));
|
||||
result.address = std::bit_cast<IP_Address>(errorEndpoint.sin_addr);
|
||||
return &result;
|
||||
}
|
||||
else
|
||||
{
|
||||
Console.Error("DEV9: ICMP: Recv Error %d", ex_err->ee_errno);
|
||||
Console.Error("DEV9: ICMP: Recv error %d", exError.ee_errno);
|
||||
result.type = -1;
|
||||
result.code = ex_err->ee_errno;
|
||||
result.code = exError.ee_errno;
|
||||
return &result;
|
||||
}
|
||||
}
|
||||
@@ -424,60 +418,66 @@ namespace Sessions
|
||||
else
|
||||
#endif
|
||||
{
|
||||
ip* ipHeader = (ip*)icmpResponseBuffer.get();
|
||||
int headerLength = ipHeader->ip_hl << 2;
|
||||
// Rely on implicit object creation
|
||||
const ip* ipHeader = reinterpret_cast<ip*>(icmpResponseBuffer.get());
|
||||
const int headerLength = ipHeader->ip_hl << 2;
|
||||
pxAssert(headerLength == 20);
|
||||
|
||||
offset = headerLength;
|
||||
#ifdef __APPLE__
|
||||
//Apple (old BSD)'s raw IP sockets implementation converts the ip_len field to host byte order
|
||||
//and additionally subtracts the header length.
|
||||
//https://www.unix.com/man-page/mojave/4/ip/
|
||||
// Apple (old BSD)'s raw IP sockets implementation converts the ip_len field to host byte order
|
||||
// and additionally subtracts the header length.
|
||||
// https://www.unix.com/man-page/mojave/4/ip/
|
||||
length = ipHeader->ip_len;
|
||||
#else
|
||||
length = ntohs(ipHeader->ip_len) - headerLength;
|
||||
#endif
|
||||
}
|
||||
|
||||
ICMP_Packet icmp(&icmpResponseBuffer[offset], length);
|
||||
// Rely on implicit object creation for u8
|
||||
ICMP_Packet icmp(reinterpret_cast<u8*>(&icmpResponseBuffer[offset]), length);
|
||||
PayloadPtr* icmpPayload = static_cast<PayloadPtr*>(icmp.GetPayload());
|
||||
|
||||
result.type = icmp.type;
|
||||
result.code = icmp.code;
|
||||
|
||||
sockaddr_in* sockaddr = (sockaddr_in*)&endpoint;
|
||||
result.address = *(IP_Address*)&sockaddr->sin_addr;
|
||||
result.address = std::bit_cast<IP_Address>(endpoint.sin_addr);
|
||||
|
||||
if (icmp.type == 0)
|
||||
{
|
||||
//Check if response is to us
|
||||
// Check if response is for us
|
||||
if (icmpConnectionKind == PingType::RAW)
|
||||
{
|
||||
ICMP_HeaderDataIdentifier headerData(icmp.headerData);
|
||||
const ICMP_HeaderDataIdentifier headerData(icmp.headerData);
|
||||
if (headerData.identifier != icmpId)
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
//While icmp (and its PayloadPtr) will be destroyed when leaving this function
|
||||
//the data pointed to it persist in icmpResponseBuffer
|
||||
// While icmp (and its PayloadPtr) will be destroyed when leaving this function
|
||||
// the data it points to persists in icmpResponseBuffer
|
||||
result.dataLength = icmpPayload->GetLength();
|
||||
result.data = icmpPayload->data;
|
||||
return &result;
|
||||
}
|
||||
#if defined(ICMP_SOCKETS_BSD)
|
||||
// On BSD/Mac, ICMP errors are returned as normal packets
|
||||
else if (icmp.type == 3 || icmp.type == 4 || icmp.type == 5 || icmp.type == 11)
|
||||
{
|
||||
//Check if response is to us
|
||||
//We need to extract the sent header
|
||||
// Extract the packet the ICMP message is responding to
|
||||
IP_Packet ipPacket(icmpPayload->data, icmpPayload->GetLength(), true);
|
||||
IP_PayloadPtr* ipPayload = static_cast<IP_PayloadPtr*>(ipPacket.GetPayload());
|
||||
ICMP_Packet retIcmp(ipPayload->data, ipPayload->GetLength());
|
||||
|
||||
ICMP_HeaderDataIdentifier headerData(icmp.headerData);
|
||||
if (ipPacket.protocol != static_cast<u8>(IP_Type::ICMP))
|
||||
return nullptr;
|
||||
|
||||
IP_PayloadPtr* ipPayload = static_cast<IP_PayloadPtr*>(ipPacket.GetPayload());
|
||||
ICMP_Packet icmpInner(ipPayload->data, ipPayload->GetLength());
|
||||
|
||||
// Check if response is for us
|
||||
const ICMP_HeaderDataIdentifier headerData(icmpInner.headerData);
|
||||
if (headerData.identifier != icmpId)
|
||||
return nullptr;
|
||||
|
||||
//This response is for us
|
||||
// This response is for us
|
||||
return &result;
|
||||
}
|
||||
#endif
|
||||
@@ -487,7 +487,7 @@ namespace Sessions
|
||||
Console.Error("DEV9: ICMP: Unexpected packet");
|
||||
pxAssert(false);
|
||||
#endif
|
||||
//Assume not for us
|
||||
// Assume not for us
|
||||
return nullptr;
|
||||
}
|
||||
}
|
||||
@@ -503,25 +503,25 @@ namespace Sessions
|
||||
bool ICMP_Session::Ping::Send(IP_Address parAdapterIP, IP_Address parDestIP, int parTimeToLive, PayloadPtr* parPayload)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
//Documentation is incorrect, IP_OPTION_INFORMATION is to be used regardless of platform
|
||||
IP_OPTION_INFORMATION ipInfo{0};
|
||||
// Documentation is incorrect, IP_OPTION_INFORMATION is to be used regardless of platform
|
||||
IP_OPTION_INFORMATION ipInfo{};
|
||||
ipInfo.Ttl = parTimeToLive;
|
||||
DWORD ret;
|
||||
if (parAdapterIP.integer != 0)
|
||||
ret = IcmpSendEcho2Ex(icmpFile, icmpEvent, nullptr, nullptr, parAdapterIP.integer, parDestIP.integer, parPayload->data, parPayload->GetLength(), &ipInfo, icmpResponseBuffer.get(), icmpResponseBufferLen,
|
||||
(DWORD)std::chrono::duration_cast<std::chrono::milliseconds>(ICMP_TIMEOUT).count());
|
||||
static_cast<DWORD>(std::chrono::duration_cast<std::chrono::milliseconds>(ICMP_TIMEOUT).count()));
|
||||
else
|
||||
ret = IcmpSendEcho2(icmpFile, icmpEvent, nullptr, nullptr, parDestIP.integer, parPayload->data, parPayload->GetLength(), &ipInfo, icmpResponseBuffer.get(), icmpResponseBufferLen,
|
||||
(DWORD)std::chrono::duration_cast<std::chrono::milliseconds>(ICMP_TIMEOUT).count());
|
||||
static_cast<DWORD>(std::chrono::duration_cast<std::chrono::milliseconds>(ICMP_TIMEOUT).count()));
|
||||
|
||||
//Documentation states that IcmpSendEcho2 returns ERROR_IO_PENDING
|
||||
//However, it actully returns zero, with the error set to ERROR_IO_PENDING
|
||||
// Documentation states that IcmpSendEcho2 returns ERROR_IO_PENDING
|
||||
// However, it actually returns zero, with the error set to ERROR_IO_PENDING
|
||||
if (ret == 0)
|
||||
ret = GetLastError();
|
||||
|
||||
if (ret != ERROR_IO_PENDING)
|
||||
{
|
||||
Console.Error("DEV9: ICMP: Failed to Send Echo, %d", GetLastError());
|
||||
Console.Error("DEV9: ICMP: Failed to send echo, %d", GetLastError());
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -534,16 +534,16 @@ namespace Sessions
|
||||
{
|
||||
icmpDeathClockStart = std::chrono::steady_clock::now();
|
||||
|
||||
//broadcast and multicast mignt need extra setsockopts
|
||||
//I don't think any game will broadcast/multicast ping
|
||||
// Broadcast and multicast might need extra setsockopts calls
|
||||
// I don't think any game will do a broadcast/multicast ping
|
||||
|
||||
if (parAdapterIP.integer != 0)
|
||||
{
|
||||
sockaddr_in endpoint{0};
|
||||
sockaddr_in endpoint{};
|
||||
endpoint.sin_family = AF_INET;
|
||||
*(IP_Address*)&endpoint.sin_addr = parAdapterIP;
|
||||
endpoint.sin_addr = std::bit_cast<in_addr>(parAdapterIP);
|
||||
|
||||
if (bind(icmpSocket, (const sockaddr*)&endpoint, sizeof(endpoint)) == -1)
|
||||
if (bind(icmpSocket, reinterpret_cast<const sockaddr*>(&endpoint), sizeof(endpoint)) == -1)
|
||||
{
|
||||
Console.Error("DEV9: ICMP: Failed to bind socket. Error: %d", errno);
|
||||
::close(icmpSocket);
|
||||
@@ -553,8 +553,8 @@ namespace Sessions
|
||||
}
|
||||
|
||||
#if defined(ICMP_SOCKETS_LINUX)
|
||||
int value = 1;
|
||||
if (setsockopt(icmpSocket, SOL_IP, IP_RECVERR, (char*)&value, sizeof(value)))
|
||||
const int value = 1;
|
||||
if (setsockopt(icmpSocket, SOL_IP, IP_RECVERR, reinterpret_cast<const char*>(&value), sizeof(value)))
|
||||
{
|
||||
Console.Error("DEV9: ICMP: Failed to setsockopt IP_RECVERR. Error: %d", errno);
|
||||
::close(icmpSocket);
|
||||
@@ -563,8 +563,8 @@ namespace Sessions
|
||||
}
|
||||
#endif
|
||||
|
||||
// TTL (Note multicast & regular ttl are seperate)
|
||||
if (setsockopt(icmpSocket, IPPROTO_IP, IP_TTL, (const char*)&parTimeToLive, sizeof(parTimeToLive)) == -1)
|
||||
// TTL (Note multicast & regular ttl are separate)
|
||||
if (setsockopt(icmpSocket, IPPROTO_IP, IP_TTL, reinterpret_cast<const char*>(&parTimeToLive), sizeof(parTimeToLive)) == -1)
|
||||
{
|
||||
Console.Error("DEV9: ICMP: Failed to set TTL. Error: %d", errno);
|
||||
::close(icmpSocket);
|
||||
@@ -572,13 +572,23 @@ namespace Sessions
|
||||
return false;
|
||||
}
|
||||
|
||||
// Non-blocking
|
||||
int blocking = 1;
|
||||
if (ioctl(icmpSocket, FIONBIO, &blocking) == -1)
|
||||
{
|
||||
Console.Error("DEV9: ICMP: Failed to set non-blocking. Error: %d", errno);
|
||||
::close(icmpSocket);
|
||||
icmpSocket = -1;
|
||||
return false;
|
||||
}
|
||||
|
||||
#if defined(ICMP_SOCKETS_LINUX)
|
||||
if (icmpConnectionKind == PingType::ICMP)
|
||||
{
|
||||
//We get assigned a port
|
||||
sockaddr_in endpoint{0};
|
||||
// We get assigned a port/Id
|
||||
sockaddr_in endpoint{};
|
||||
socklen_t endpointsize = sizeof(endpoint);
|
||||
if (getsockname(icmpSocket, (sockaddr*)&endpoint, &endpointsize) == -1)
|
||||
if (getsockname(icmpSocket, reinterpret_cast<sockaddr*>(&endpoint), &endpointsize) == -1)
|
||||
{
|
||||
Console.Error("DEV9: ICMP: Failed to get id. Error: %d", errno);
|
||||
::close(icmpSocket);
|
||||
@@ -591,15 +601,15 @@ namespace Sessions
|
||||
else
|
||||
#endif
|
||||
{
|
||||
//Use time, in ms, as id
|
||||
icmpId = (u16)std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count();
|
||||
// Use time, in ms, as id
|
||||
icmpId = static_cast<u16>(std::chrono::duration_cast<std::chrono::milliseconds>(std::chrono::system_clock::now().time_since_epoch()).count());
|
||||
}
|
||||
|
||||
ICMP_Packet icmp(parPayload->Clone());
|
||||
icmp.type = 8;
|
||||
icmp.code = 0;
|
||||
|
||||
//We only send one icmp packet per identifier
|
||||
// We only send one icmp packet per identifier
|
||||
ICMP_HeaderDataIdentifier headerData(icmpId, 1);
|
||||
headerData.WriteHeaderData(icmp.headerData);
|
||||
|
||||
@@ -609,17 +619,27 @@ namespace Sessions
|
||||
int offset = 0;
|
||||
icmp.WriteBytes(buffer.get(), &offset);
|
||||
|
||||
sockaddr_in endpoint{0};
|
||||
sockaddr_in endpoint{};
|
||||
endpoint.sin_family = AF_INET;
|
||||
*(IP_Address*)&endpoint.sin_addr.s_addr = parDestIP;
|
||||
endpoint.sin_addr = std::bit_cast<in_addr>(parDestIP);
|
||||
|
||||
const int ret = sendto(icmpSocket, buffer.get(), icmp.GetLength(), 0, (const sockaddr*)&endpoint, sizeof(endpoint));
|
||||
if (ret == -1)
|
||||
int ret = -1;
|
||||
while (ret == -1)
|
||||
{
|
||||
Console.Error("DEV9: ICMP: Send Error %d", errno);
|
||||
::close(icmpSocket);
|
||||
icmpSocket = -1;
|
||||
return false;
|
||||
ret = sendto(icmpSocket, buffer.get(), icmp.GetLength(), 0, reinterpret_cast<const sockaddr*>(&endpoint), sizeof(endpoint));
|
||||
if (ret == -1)
|
||||
{
|
||||
const int err = errno;
|
||||
if (err == EAGAIN || err == EWOULDBLOCK)
|
||||
std::this_thread::yield();
|
||||
else
|
||||
{
|
||||
Console.Error("DEV9: ICMP: Send error %d", errno);
|
||||
::close(icmpSocket);
|
||||
icmpSocket = -1;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
@@ -665,16 +685,15 @@ namespace Sessions
|
||||
|
||||
for (size_t i = 0; i < pings.size(); i++)
|
||||
{
|
||||
ICMP_Session::PingResult* pingRet = nullptr;
|
||||
pingRet = pings[i]->Recv();
|
||||
const ICMP_Session::PingResult* pingRet = pings[i]->Recv();
|
||||
if (pingRet != nullptr)
|
||||
{
|
||||
Ping* ping = pings[i];
|
||||
//Remove ping from list and unlock
|
||||
std::unique_ptr<Ping> ping = std::move(pings[i]);
|
||||
// Remove ping from list and unlock mutex
|
||||
pings.erase(pings.begin() + i);
|
||||
lock.unlock();
|
||||
|
||||
//Create return ICMP packet
|
||||
// Create return ICMP packet
|
||||
std::optional<ReceivedPayload> ret;
|
||||
if (pingRet->type >= 0)
|
||||
{
|
||||
@@ -686,22 +705,19 @@ namespace Sessions
|
||||
}
|
||||
else
|
||||
{
|
||||
//We will copy the original packet back here
|
||||
//Allocate fullsize buffer
|
||||
u8* temp = new u8[ping->originalPacket->GetLength()];
|
||||
//Allocate data
|
||||
int responseSize = ping->originalPacket->GetHeaderLength() + 8;
|
||||
// Copy the original packet into the returned ICMP packet
|
||||
// Allocate fullsize buffer
|
||||
std::vector<u8> temp = std::vector<u8>(ping->originalPacket->GetLength());
|
||||
// Allocate returned ICMP payload
|
||||
const int responseSize = ping->originalPacket->GetHeaderLength() + 8;
|
||||
data = new PayloadData(responseSize);
|
||||
|
||||
//Write packet back into bytes
|
||||
// Write packet into buffer
|
||||
int offset = 0;
|
||||
ping->originalPacket->WriteBytes(temp, &offset);
|
||||
ping->originalPacket->WriteBytes(temp.data(), &offset);
|
||||
|
||||
//Copy only needed bytes
|
||||
memcpy(data->data.get(), temp, responseSize);
|
||||
|
||||
//cleanup
|
||||
delete[] temp;
|
||||
// Copy only needed bytes
|
||||
memcpy(data->data.get(), temp.data(), responseSize);
|
||||
}
|
||||
|
||||
std::unique_ptr<ICMP_Packet> pRet = std::make_unique<ICMP_Packet>(data);
|
||||
@@ -716,16 +732,13 @@ namespace Sessions
|
||||
else
|
||||
DevCon.WriteLn("DEV9: ICMP: ICMP timeout");
|
||||
|
||||
//free ping
|
||||
delete ping;
|
||||
if (ret.has_value())
|
||||
DevCon.WriteLn("DEV9: ICMP: Return Ping");
|
||||
|
||||
if (--open == 0)
|
||||
RaiseEventConnectionClosed();
|
||||
|
||||
if (ret.has_value())
|
||||
DevCon.WriteLn("DEV9: ICMP: Return Ping");
|
||||
|
||||
//Return packet
|
||||
// Return packet
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
@@ -741,7 +754,7 @@ namespace Sessions
|
||||
return false;
|
||||
}
|
||||
|
||||
//Note, expects caller to set ipTimeToLive before calling
|
||||
// Expects caller to set ipTimeToLive before calling
|
||||
bool ICMP_Session::Send(PacketReader::IP::IP_Payload* payload, IP_Packet* packet)
|
||||
{
|
||||
IP_PayloadPtr* ipPayload = static_cast<IP_PayloadPtr*>(payload);
|
||||
@@ -751,16 +764,19 @@ namespace Sessions
|
||||
|
||||
switch (icmp.type)
|
||||
{
|
||||
case 3: //Port Closed
|
||||
case 3: // Port Closed
|
||||
switch (icmp.code)
|
||||
{
|
||||
case 3:
|
||||
{
|
||||
Console.Error("DEV9: ICMP: Recived Packet Rejected, Port Closed");
|
||||
|
||||
//RE:Outbreak Hackfix
|
||||
//TODO, check if still needed
|
||||
Console.Error("DEV9: ICMP: Received Packet Rejected, Port Closed");
|
||||
|
||||
/*
|
||||
* RE:Outbreak Hackfix
|
||||
* ICMP port closed messages has an extra 4 bytes of padding before the packet copy
|
||||
* this can be tested by trying to connect without using the resurrection server DNS
|
||||
* turbo mode may be needed to trigger the bug, depending on the DNS server's latency
|
||||
*/
|
||||
std::unique_ptr<IP_Packet> retPkt;
|
||||
if ((icmpPayload->data[0] & 0xF0) == (4 << 4))
|
||||
retPkt = std::make_unique<IP_Packet>(icmpPayload->data, icmpPayload->GetLength(), true);
|
||||
@@ -776,20 +792,20 @@ namespace Sessions
|
||||
retPkt = std::make_unique<IP_Packet>(&icmpPayload->data[off], icmpPayload->GetLength(), true);
|
||||
}
|
||||
|
||||
IP_Address srvIP = retPkt->sourceIP;
|
||||
u8 prot = retPkt->protocol;
|
||||
const IP_Address srvIP = retPkt->sourceIP;
|
||||
const u8 prot = retPkt->protocol;
|
||||
u16 srvPort = 0;
|
||||
u16 ps2Port = 0;
|
||||
switch (prot)
|
||||
{
|
||||
case (u8)IP_Type::TCP:
|
||||
case (u8)IP_Type::UDP:
|
||||
//Read ports directly from the payload
|
||||
//both UDP and TCP have the same locations for ports
|
||||
case static_cast<u8>(IP_Type::TCP):
|
||||
case static_cast<u8>(IP_Type::UDP):
|
||||
// Read ports directly from the payload
|
||||
// both UDP and TCP have the same locations for ports
|
||||
IP_PayloadPtr* payload = static_cast<IP_PayloadPtr*>(retPkt->GetPayload());
|
||||
int offset = 0;
|
||||
NetLib::ReadUInt16(payload->data, &offset, &srvPort); //src
|
||||
NetLib::ReadUInt16(payload->data, &offset, &ps2Port); //dst
|
||||
NetLib::ReadUInt16(payload->data, &offset, &srvPort); // src
|
||||
NetLib::ReadUInt16(payload->data, &offset, &ps2Port); // dst
|
||||
}
|
||||
|
||||
ConnectionKey Key{};
|
||||
@@ -798,7 +814,7 @@ namespace Sessions
|
||||
Key.ps2Port = ps2Port;
|
||||
Key.srvPort = srvPort;
|
||||
|
||||
//is from Normal Port?
|
||||
// Is from Normal Port?
|
||||
BaseSession* s = nullptr;
|
||||
connections->TryGetValue(Key, &s);
|
||||
|
||||
@@ -809,7 +825,7 @@ namespace Sessions
|
||||
break;
|
||||
}
|
||||
|
||||
//Is from Fixed Port?
|
||||
// Is from Fixed Port?
|
||||
Key.ip = {};
|
||||
Key.srvPort = 0;
|
||||
connections->TryGetValue(Key, &s);
|
||||
@@ -827,18 +843,17 @@ namespace Sessions
|
||||
Console.Error("DEV9: ICMP: Unsupported ICMP Code For Destination Unreachable %d", icmp.code);
|
||||
}
|
||||
break;
|
||||
case 8: //Echo
|
||||
case 8: // Echo
|
||||
{
|
||||
DevCon.WriteLn("DEV9: ICMP: Send Ping");
|
||||
open++;
|
||||
|
||||
Ping* ping = new Ping(icmpPayload->GetLength());
|
||||
std::unique_ptr<Ping> ping = std::make_unique<Ping>(icmpPayload->GetLength());
|
||||
|
||||
if (!ping->IsInitialised())
|
||||
{
|
||||
if (--open == 0)
|
||||
RaiseEventConnectionClosed();
|
||||
delete ping;
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -846,18 +861,17 @@ namespace Sessions
|
||||
{
|
||||
if (--open == 0)
|
||||
RaiseEventConnectionClosed();
|
||||
delete ping;
|
||||
return false;
|
||||
}
|
||||
|
||||
memcpy(ping->headerData, icmp.headerData, 4);
|
||||
|
||||
//Need to copy IP_Packet, original is stack allocated
|
||||
// Need to copy IP_Packet, original is stack allocated
|
||||
ping->originalPacket = std::make_unique<IP_Packet>(*packet);
|
||||
|
||||
{
|
||||
std::scoped_lock lock(ping_mutex);
|
||||
pings.push_back(ping);
|
||||
pings.push_back(std::move(ping));
|
||||
}
|
||||
|
||||
break;
|
||||
@@ -876,10 +890,8 @@ namespace Sessions
|
||||
|
||||
ICMP_Session::~ICMP_Session()
|
||||
{
|
||||
// Cleanup
|
||||
std::scoped_lock lock(ping_mutex);
|
||||
|
||||
//Cleanup
|
||||
for (size_t i = 0; i < pings.size(); i++)
|
||||
delete pings[i];
|
||||
pings.clear();
|
||||
}
|
||||
} // namespace Sessions
|
||||
|
||||
@@ -47,30 +47,29 @@ namespace Sessions
|
||||
|
||||
static PingType icmpConnectionKind;
|
||||
|
||||
//Sockets
|
||||
// Sockets
|
||||
int icmpSocket{-1};
|
||||
std::chrono::steady_clock::time_point icmpDeathClockStart;
|
||||
u16 icmpId;
|
||||
|
||||
#endif
|
||||
|
||||
//Return buffers
|
||||
// Return buffers
|
||||
PingResult result{};
|
||||
int icmpResponseBufferLen{0};
|
||||
std::unique_ptr<u8[]> icmpResponseBuffer;
|
||||
std::unique_ptr<std::byte[]> icmpResponseBuffer;
|
||||
|
||||
public:
|
||||
Ping(int requestSize);
|
||||
bool IsInitialised();
|
||||
bool IsInitialised() const;
|
||||
PingResult* Recv();
|
||||
bool Send(PacketReader::IP::IP_Address parAdapterIP, PacketReader::IP::IP_Address parDestIP, int parTimeToLive, PacketReader::PayloadPtr* parPayload);
|
||||
|
||||
~Ping();
|
||||
};
|
||||
|
||||
SimpleQueue<PacketReader::IP::ICMP::ICMP_Packet*> _recvBuff;
|
||||
std::mutex ping_mutex;
|
||||
std::vector<Ping*> pings;
|
||||
std::vector<std::unique_ptr<Ping>> pings;
|
||||
ThreadSafeMap<Sessions::ConnectionKey, Sessions::BaseSession*>* connections;
|
||||
|
||||
std::atomic<int> open{0};
|
||||
|
||||
@@ -1054,6 +1054,7 @@ static void HotkeyToggleOSD()
|
||||
GSConfig.OsdShowSettings ^= EmuConfig.GS.OsdShowSettings;
|
||||
GSConfig.OsdShowInputs ^= EmuConfig.GS.OsdShowInputs;
|
||||
GSConfig.OsdShowFrameTimes ^= EmuConfig.GS.OsdShowFrameTimes;
|
||||
GSConfig.OsdShowVersion ^= EmuConfig.GS.OsdShowVersion;
|
||||
}
|
||||
|
||||
BEGIN_HOTKEY_LIST(g_gs_hotkeys){"Screenshot", TRANSLATE_NOOP("Hotkeys", "Graphics"),
|
||||
|
||||
@@ -460,6 +460,8 @@ bool GSCapture::BeginCapture(float fps, GSVector2i recommendedResolution, float
|
||||
}
|
||||
}
|
||||
}
|
||||
if (sw_pix_fmt == AV_PIX_FMT_VAAPI)
|
||||
sw_pix_fmt = AV_PIX_FMT_NV12;
|
||||
s_video_codec_context->pix_fmt = sw_pix_fmt;
|
||||
|
||||
// Can we use hardware encoding?
|
||||
|
||||
@@ -4668,7 +4668,6 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
blend.op = GSDevice::OP_ADD;
|
||||
// Render pass 2: Add or subtract result of render pass 1(Cd) from Cs.
|
||||
m_conf.blend_second_pass.enable = true;
|
||||
m_conf.blend_second_pass.blend_hw = 0;
|
||||
m_conf.blend_second_pass.dither = dither * GSConfig.Dithering;
|
||||
m_conf.blend_second_pass.blend = {true, blend_second_pass.src, GSDevice::CONST_ONE, blend_second_pass.op, GSDevice::CONST_ONE, GSDevice::CONST_ZERO, false, 0};
|
||||
}
|
||||
@@ -4743,8 +4742,12 @@ void GSRendererHW::EmulateBlending(int rt_alpha_min, int rt_alpha_max, const boo
|
||||
m_conf.ps.blend_hw = static_cast<u8>(HWBlendType::SRC_DOUBLE);
|
||||
}
|
||||
|
||||
if (m_conf.ps.blend_c == 2 && (m_conf.ps.blend_hw == 2 || m_conf.ps.blend_hw == 4 || m_conf.blend_second_pass.blend_hw == 2))
|
||||
if (m_conf.ps.blend_c == 2 && (m_conf.ps.blend_hw == static_cast<u8>(HWBlendType::SRC_ALPHA_DST_FACTOR)
|
||||
|| m_conf.ps.blend_hw == static_cast<u8>(HWBlendType::SRC_HALF_ONE_DST_FACTOR)
|
||||
|| m_conf.blend_second_pass.blend_hw == static_cast<u8>(HWBlendType::SRC_ALPHA_DST_FACTOR)))
|
||||
{
|
||||
m_conf.cb_ps.TA_MaxDepth_Af.a = static_cast<float>(AFIX) / 128.0f;
|
||||
}
|
||||
|
||||
const GSDevice::BlendFactor src_factor_alpha = m_conf.blend_second_pass.enable ? GSDevice::CONST_ZERO : GSDevice::CONST_ONE;
|
||||
const GSDevice::BlendFactor dst_factor_alpha = m_conf.blend_second_pass.enable ? GSDevice::CONST_ONE : GSDevice::CONST_ZERO;
|
||||
|
||||
@@ -3123,6 +3123,9 @@ void FullscreenUI::DrawInterfaceSettingsPage()
|
||||
FSUI_CSTR(
|
||||
"Shows on-screen-display messages when events occur such as save states being created/loaded, screenshots being taken, etc."),
|
||||
"EmuCore/GS", "OsdShowMessages", true);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_INFO, "Show PCSX2 Version"),
|
||||
FSUI_CSTR("Shows the current PCSX2 version on the top-right corner of the display."), "EmuCore/GS",
|
||||
"OsdShowVersion", false);
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_TACHOMETER_ALT, "Show Speed"),
|
||||
FSUI_CSTR("Shows the current emulation speed of the system in the top-right corner of the display as a percentage."), "EmuCore/GS",
|
||||
"OsdShowSpeed", false);
|
||||
@@ -3287,11 +3290,11 @@ void FullscreenUI::DrawEmulationSettingsPage()
|
||||
|
||||
MenuHeading(FSUI_CSTR("Speed Control"));
|
||||
|
||||
DrawFloatListSetting(bsi, FSUI_ICONSTR(ICON_FA_PLAY,"Normal Speed"), FSUI_CSTR("Sets the speed when running without fast forwarding."), "Framerate",
|
||||
DrawFloatListSetting(bsi, FSUI_ICONSTR(ICON_FA_PLAY, "Normal Speed"), FSUI_CSTR("Sets the speed when running without fast forwarding."), "Framerate",
|
||||
"NominalScalar", 1.00f, speed_entries, speed_values, std::size(speed_entries), true);
|
||||
DrawFloatListSetting(bsi, FSUI_ICONSTR(ICON_FA_FAST_FORWARD,"Fast Forward Speed"), FSUI_CSTR("Sets the speed when using the fast forward hotkey."), "Framerate",
|
||||
DrawFloatListSetting(bsi, FSUI_ICONSTR(ICON_FA_FAST_FORWARD, "Fast Forward Speed"), FSUI_CSTR("Sets the speed when using the fast forward hotkey."), "Framerate",
|
||||
"TurboScalar", 2.00f, speed_entries, speed_values, std::size(speed_entries), true);
|
||||
DrawFloatListSetting(bsi, FSUI_ICONSTR(ICON_PF_SLOW_MOTION,"Slow Motion Speed"), FSUI_CSTR("Sets the speed when using the slow motion hotkey."), "Framerate",
|
||||
DrawFloatListSetting(bsi, FSUI_ICONSTR(ICON_PF_SLOW_MOTION, "Slow Motion Speed"), FSUI_CSTR("Sets the speed when using the slow motion hotkey."), "Framerate",
|
||||
"SlomoScalar", 0.50f, speed_entries, speed_values, std::size(speed_entries), true);
|
||||
|
||||
MenuHeading(FSUI_CSTR("System Settings"));
|
||||
@@ -3597,7 +3600,7 @@ void FullscreenUI::DrawGraphicsSettingsPage(SettingsInterface* bsi, bool show_ad
|
||||
BeginMenuButtons();
|
||||
|
||||
MenuHeading(FSUI_CSTR("Renderer"));
|
||||
DrawStringListSetting(bsi, FSUI_ICONSTR(ICON_FA_PAINT_BRUSH,"Renderer"), FSUI_CSTR("Selects the API used to render the emulated GS."), "EmuCore/GS",
|
||||
DrawStringListSetting(bsi, FSUI_ICONSTR(ICON_FA_PAINT_BRUSH, "Renderer"), FSUI_CSTR("Selects the API used to render the emulated GS."), "EmuCore/GS",
|
||||
"Renderer", "-1", s_renderer_names, s_renderer_values, std::size(s_renderer_names), true);
|
||||
|
||||
MenuHeading(FSUI_CSTR("Display"));
|
||||
@@ -3950,7 +3953,7 @@ void FullscreenUI::DrawAudioSettingsPage()
|
||||
DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_VOLUME_UP, "Output Volume"),
|
||||
FSUI_CSTR("Controls the volume of the audio played on the host."), "SPU2/Output", "OutputVolume", 100,
|
||||
0, 100, "%d%%");
|
||||
DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_FAST_FORWARD,"Fast Forward Volume"),
|
||||
DrawIntRangeSetting(bsi, FSUI_ICONSTR(ICON_FA_FAST_FORWARD, "Fast Forward Volume"),
|
||||
FSUI_CSTR("Controls the volume of the audio played on the host when fast forwarding."), "SPU2/Output",
|
||||
"FastForwardVolume", 100, 0, 100, "%d%%");
|
||||
DrawToggleSetting(bsi, FSUI_ICONSTR(ICON_FA_VOLUME_MUTE, "Mute All Sound"),
|
||||
|
||||
@@ -24,6 +24,7 @@
|
||||
#include "SIO/Pad/PadBase.h"
|
||||
#include "USB/USB.h"
|
||||
#include "VMManager.h"
|
||||
#include "svnrev.h"
|
||||
|
||||
#include "common/BitUtils.h"
|
||||
#include "common/FileSystem.h"
|
||||
@@ -121,6 +122,7 @@ __ri void ImGuiManager::DrawPerformanceOverlay(float& position_y, float scale, f
|
||||
{
|
||||
bool first = true;
|
||||
const float speed = PerformanceMetrics::GetSpeed();
|
||||
|
||||
if (GSConfig.OsdShowFPS)
|
||||
{
|
||||
switch (PerformanceMetrics::GetInternalFPSMethod())
|
||||
@@ -152,6 +154,16 @@ __ri void ImGuiManager::DrawPerformanceOverlay(float& position_y, float scale, f
|
||||
else
|
||||
text.append_format(" ({:.0f}%)", target_speed * 100.0f);
|
||||
}
|
||||
|
||||
if (GSConfig.OsdShowVersion)
|
||||
{
|
||||
if (GSConfig.OsdShowFPS || GSConfig.OsdShowSpeed)
|
||||
{
|
||||
text.append_format(" | ");
|
||||
}
|
||||
text.append_format("PCSX2 {}", GIT_REV);
|
||||
}
|
||||
|
||||
if (!text.empty())
|
||||
{
|
||||
ImU32 color;
|
||||
|
||||
@@ -39,18 +39,18 @@ void iopMemRelease()
|
||||
// which is performed by MemInit and PsxMemInit()
|
||||
void iopMemReset()
|
||||
{
|
||||
pxAssert( iopMem );
|
||||
pxAssert(iopMem);
|
||||
|
||||
DbgCon.WriteLn("IOP resetting main memory...");
|
||||
|
||||
memset(psxMemWLUT, 0, 0x2000 * sizeof(uptr) * 2); // clears both allocations, RLUT and WLUT
|
||||
memset(psxMemWLUT, 0, 0x2000 * sizeof(uptr) * 2); // clears both allocations, RLUT and WLUT
|
||||
|
||||
// Trick! We're accessing RLUT here through WLUT, since it's the non-const pointer.
|
||||
// So the ones with a 0x2000 prefixed are RLUT tables.
|
||||
|
||||
// Map IOP main memory, which is Read/Write, and mirrored three times
|
||||
// at 0x0, 0x8000, and 0xa000:
|
||||
for (int i=0; i<0x0080; i++)
|
||||
for (int i = 0; i < 0x0080; i++)
|
||||
{
|
||||
psxMemWLUT[i + 0x0000] = (uptr)&iopMem->Main[(i & 0x1f) << 16];
|
||||
|
||||
@@ -78,7 +78,7 @@ void iopMemReset()
|
||||
psxMemWLUT[i + 0x2000 + 0x1e00] = (uptr)&eeMem->ROM1[i << 16];
|
||||
}
|
||||
|
||||
for (int i = 0; i < 0x0008; i++)
|
||||
for (int i = 0; i < 0x0040; i++)
|
||||
{
|
||||
psxMemWLUT[i + 0x2000 + 0x1e40] = (uptr)&eeMem->ROM2[i << 16];
|
||||
}
|
||||
@@ -318,7 +318,7 @@ void iopMemWrite16(u32 mem, u16 value)
|
||||
|
||||
default:
|
||||
psxHu16(mem) = value;
|
||||
break;
|
||||
break;
|
||||
}
|
||||
} else
|
||||
{
|
||||
@@ -443,7 +443,7 @@ void iopMemWrite32(u32 mem, u32 value)
|
||||
|
||||
case 0x60:
|
||||
psHu32(SBUS_F260) = 0;
|
||||
return;
|
||||
return;
|
||||
|
||||
}
|
||||
#if PSX_EXTRALOGS
|
||||
@@ -529,11 +529,11 @@ bool iopMemSafeWriteBytes(u32 mem, const void* src, u32 size)
|
||||
|
||||
std::string iopMemReadString(u32 mem, int maxlen)
|
||||
{
|
||||
std::string ret;
|
||||
char c;
|
||||
std::string ret;
|
||||
char c;
|
||||
|
||||
while ((c = iopMemRead8(mem++)) && maxlen--)
|
||||
ret.push_back(c);
|
||||
while ((c = iopMemRead8(mem++)) && maxlen--)
|
||||
ret.push_back(c);
|
||||
|
||||
return ret;
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace Ps2MemSize
|
||||
static constexpr u32 TotalRam = _1mb * 128;// 128 MB total memory.
|
||||
static constexpr u32 Rom = _1mb * 4; // 4 MB main rom
|
||||
static constexpr u32 Rom1 = _1mb * 4; // DVD player
|
||||
static constexpr u32 Rom2 = 0x00080000; // Chinese rom extension
|
||||
static constexpr u32 Rom2 = _1mb * 4; // Chinese rom extension
|
||||
static constexpr u32 Hardware = _64kb;
|
||||
static constexpr u32 Scratch = _16kb;
|
||||
|
||||
|
||||
@@ -629,6 +629,7 @@ Pcsx2Config::GSOptions::GSOptions()
|
||||
OsdShowSettings = false;
|
||||
OsdShowInputs = false;
|
||||
OsdShowFrameTimes = false;
|
||||
OsdShowVersion = false;
|
||||
|
||||
HWDownloadMode = GSHardwareDownloadMode::Enabled;
|
||||
HWSpinGPUForReadbacks = false;
|
||||
@@ -833,6 +834,7 @@ void Pcsx2Config::GSOptions::LoadSave(SettingsWrapper& wrap)
|
||||
SettingsWrapBitBool(OsdShowSettings);
|
||||
SettingsWrapBitBool(OsdShowInputs);
|
||||
SettingsWrapBitBool(OsdShowFrameTimes);
|
||||
SettingsWrapBitBool(OsdShowVersion);
|
||||
|
||||
SettingsWrapBitBool(HWSpinGPUForReadbacks);
|
||||
SettingsWrapBitBool(HWSpinCPUForReadbacks);
|
||||
|
||||
@@ -548,7 +548,7 @@ static void recReserveRAM()
|
||||
recLUT_SetPage(recLUT, hwLUT, recROM1, 0xa000, i, i - 0x1e00);
|
||||
}
|
||||
|
||||
for (int i = 0x1e40; i < 0x1e48; i++)
|
||||
for (int i = 0x1e40; i < 0x1e80; i++)
|
||||
{
|
||||
recLUT_SetPage(recLUT, hwLUT, recROM2, 0x0000, i, i - 0x1e40);
|
||||
recLUT_SetPage(recLUT, hwLUT, recROM2, 0x8000, i, i - 0x1e40);
|
||||
@@ -691,7 +691,7 @@ static void recExecute()
|
||||
if (!fastjmp_set(&m_SetJmp_StateCheck))
|
||||
{
|
||||
eeCpuExecuting = true;
|
||||
((void(*)())EnterRecompiledCode)();
|
||||
((void (*)())EnterRecompiledCode)();
|
||||
|
||||
// Generally unreachable code here ...
|
||||
}
|
||||
@@ -1544,7 +1544,7 @@ void dynarecMemcheck(size_t i)
|
||||
|
||||
auto mc = CBreakPoints::GetMemChecks(BREAKPOINT_EE)[i];
|
||||
|
||||
if(mc.hasCond)
|
||||
if (mc.hasCond)
|
||||
{
|
||||
if (!mc.cond.Evaluate())
|
||||
return;
|
||||
@@ -1557,7 +1557,7 @@ void dynarecMemcheck(size_t i)
|
||||
else
|
||||
DevCon.WriteLn("Hit load breakpoint @0x%x", cpuRegs.pc);
|
||||
}
|
||||
|
||||
|
||||
CBreakPoints::SetBreakpointTriggered(true, BREAKPOINT_EE);
|
||||
VMManager::SetPaused(true);
|
||||
recExitExecution();
|
||||
|
||||
Reference in New Issue
Block a user