summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--externals/ffmpeg/CMakeLists.txt4
-rw-r--r--src/android/app/src/main/AndroidManifest.xml1
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt13
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt17
-rw-r--r--src/android/app/src/main/java/org/yuzu/yuzu_emu/views/FixedRatioSurfaceView.kt48
-rw-r--r--src/audio_core/renderer/system.cpp2
-rw-r--r--src/audio_core/sink/cubeb_sink.cpp7
-rw-r--r--src/audio_core/sink/sink_details.cpp4
-rw-r--r--src/core/hle/service/audio/hwopus.cpp49
-rw-r--r--src/core/hle/service/audio/hwopus.h5
-rw-r--r--src/core/hle/service/sockets/nsd.cpp11
-rw-r--r--src/core/hle/service/sockets/sfdnsres.cpp12
-rw-r--r--src/video_core/host1x/codecs/codec.cpp3
13 files changed, 113 insertions, 63 deletions
diff --git a/externals/ffmpeg/CMakeLists.txt b/externals/ffmpeg/CMakeLists.txt
index 0a926e399..f2886eb6c 100644
--- a/externals/ffmpeg/CMakeLists.txt
+++ b/externals/ffmpeg/CMakeLists.txt
@@ -164,7 +164,7 @@ if (NOT WIN32 AND NOT ANDROID)
--enable-decoder=h264
--enable-decoder=vp8
--enable-decoder=vp9
- --enable-filter=yadif
+ --enable-filter=yadif,scale
--cc="${FFmpeg_CC}"
--cxx="${FFmpeg_CXX}"
${FFmpeg_HWACCEL_FLAGS}
@@ -254,7 +254,7 @@ elseif(ANDROID)
set(FFmpeg_INCLUDE_DIR "${FFmpeg_INCLUDE_DIR}" PARENT_SCOPE)
elseif(WIN32)
# Use yuzu FFmpeg binaries
- set(FFmpeg_EXT_NAME "ffmpeg-5.1.3")
+ set(FFmpeg_EXT_NAME "ffmpeg-6.0")
set(FFmpeg_PATH "${CMAKE_BINARY_DIR}/externals/${FFmpeg_EXT_NAME}")
download_bundled_external("ffmpeg/" ${FFmpeg_EXT_NAME} "")
set(FFmpeg_FOUND YES)
diff --git a/src/android/app/src/main/AndroidManifest.xml b/src/android/app/src/main/AndroidManifest.xml
index 36e2dac98..933244140 100644
--- a/src/android/app/src/main/AndroidManifest.xml
+++ b/src/android/app/src/main/AndroidManifest.xml
@@ -56,7 +56,6 @@ SPDX-License-Identifier: GPL-3.0-or-later
android:name="org.yuzu.yuzu_emu.activities.EmulationActivity"
android:theme="@style/Theme.Yuzu.Main"
android:launchMode="singleTop"
- android:screenOrientation="userLandscape"
android:supportsPictureInPicture="true"
android:configChanges="orientation|screenSize|smallestScreenSize|screenLayout|uiMode"
android:exported="true">
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt
index a5af5a7ae..e6fffc832 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/features/settings/ui/SettingsActivity.kt
@@ -11,7 +11,6 @@ import android.view.View
import android.view.ViewGroup.MarginLayoutParams
import android.widget.Toast
import androidx.activity.OnBackPressedCallback
-import androidx.activity.result.ActivityResultLauncher
import androidx.activity.viewModels
import androidx.appcompat.app.AppCompatActivity
import androidx.core.view.ViewCompat
@@ -246,17 +245,5 @@ class SettingsActivity : AppCompatActivity(), SettingsActivityView {
settings.putExtra(ARG_GAME_ID, gameId)
context.startActivity(settings)
}
-
- fun launch(
- context: Context,
- launcher: ActivityResultLauncher<Intent>,
- menuTag: String?,
- gameId: String?
- ) {
- val settings = Intent(context, SettingsActivity::class.java)
- settings.putExtra(ARG_MENU_TAG, menuTag)
- settings.putExtra(ARG_GAME_ID, gameId)
- launcher.launch(settings)
- }
}
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
index 25b9d4018..09e93a017 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/fragments/EmulationFragment.kt
@@ -7,7 +7,6 @@ import android.annotation.SuppressLint
import android.app.AlertDialog
import android.content.Context
import android.content.DialogInterface
-import android.content.Intent
import android.content.SharedPreferences
import android.content.pm.ActivityInfo
import android.content.res.Configuration
@@ -19,8 +18,6 @@ import android.util.Rational
import android.view.*
import android.widget.TextView
import androidx.activity.OnBackPressedCallback
-import androidx.activity.result.ActivityResultLauncher
-import androidx.activity.result.contract.ActivityResultContracts
import androidx.appcompat.widget.PopupMenu
import androidx.core.content.res.ResourcesCompat
import androidx.core.graphics.Insets
@@ -66,8 +63,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
private var isInFoldableLayout = false
- private lateinit var onReturnFromSettings: ActivityResultLauncher<Intent>
-
override fun onAttach(context: Context) {
super.onAttach(context)
if (context is EmulationActivity) {
@@ -81,11 +76,6 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
.collect { updateFoldableLayout(context, it) }
}
}
-
- onReturnFromSettings = context.activityResultRegistry.register(
- "SettingsResult",
- ActivityResultContracts.StartActivityForResult()
- ) { updateScreenLayout() }
} else {
throw IllegalStateException("EmulationFragment must have EmulationActivity parent")
}
@@ -149,12 +139,7 @@ class EmulationFragment : Fragment(), SurfaceHolder.Callback {
}
R.id.menu_settings -> {
- SettingsActivity.launch(
- requireContext(),
- onReturnFromSettings,
- SettingsFile.FILE_NAME_CONFIG,
- ""
- )
+ SettingsActivity.launch(requireContext(), SettingsFile.FILE_NAME_CONFIG, "")
true
}
diff --git a/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/FixedRatioSurfaceView.kt b/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/FixedRatioSurfaceView.kt
index 685ccaa76..2f0868c63 100644
--- a/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/FixedRatioSurfaceView.kt
+++ b/src/android/app/src/main/java/org/yuzu/yuzu_emu/views/FixedRatioSurfaceView.kt
@@ -7,7 +7,6 @@ import android.content.Context
import android.util.AttributeSet
import android.util.Rational
import android.view.SurfaceView
-import kotlin.math.roundToInt
class FixedRatioSurfaceView @JvmOverloads constructor(
context: Context,
@@ -22,27 +21,44 @@ class FixedRatioSurfaceView @JvmOverloads constructor(
*/
fun setAspectRatio(ratio: Rational?) {
aspectRatio = ratio?.toFloat() ?: 0f
+ requestLayout()
}
override fun onMeasure(widthMeasureSpec: Int, heightMeasureSpec: Int) {
- super.onMeasure(widthMeasureSpec, heightMeasureSpec)
- val width = MeasureSpec.getSize(widthMeasureSpec)
- val height = MeasureSpec.getSize(heightMeasureSpec)
+ val displayWidth: Float = MeasureSpec.getSize(widthMeasureSpec).toFloat()
+ val displayHeight: Float = MeasureSpec.getSize(heightMeasureSpec).toFloat()
if (aspectRatio != 0f) {
- val newWidth: Int
- val newHeight: Int
- if (height * aspectRatio < width) {
- newWidth = (height * aspectRatio).roundToInt()
- newHeight = height
+ val displayAspect = displayWidth / displayHeight
+ if (displayAspect < aspectRatio) {
+ // Max out width
+ val halfHeight = displayHeight / 2
+ val surfaceHeight = displayWidth / aspectRatio
+ val newTop: Float = halfHeight - (surfaceHeight / 2)
+ val newBottom: Float = halfHeight + (surfaceHeight / 2)
+ super.onMeasure(
+ widthMeasureSpec,
+ MeasureSpec.makeMeasureSpec(
+ newBottom.toInt() - newTop.toInt(),
+ MeasureSpec.EXACTLY
+ )
+ )
+ return
} else {
- newWidth = width
- newHeight = (width / aspectRatio).roundToInt()
+ // Max out height
+ val halfWidth = displayWidth / 2
+ val surfaceWidth = displayHeight * aspectRatio
+ val newLeft: Float = halfWidth - (surfaceWidth / 2)
+ val newRight: Float = halfWidth + (surfaceWidth / 2)
+ super.onMeasure(
+ MeasureSpec.makeMeasureSpec(
+ newRight.toInt() - newLeft.toInt(),
+ MeasureSpec.EXACTLY
+ ),
+ heightMeasureSpec
+ )
+ return
}
- val left = (width - newWidth) / 2
- val top = (height - newHeight) / 2
- setLeftTopRightBottom(left, top, left + newWidth, top + newHeight)
- } else {
- setLeftTopRightBottom(0, 0, width, height)
}
+ super.onMeasure(widthMeasureSpec, heightMeasureSpec)
}
}
diff --git a/src/audio_core/renderer/system.cpp b/src/audio_core/renderer/system.cpp
index a23627472..6e07baa54 100644
--- a/src/audio_core/renderer/system.cpp
+++ b/src/audio_core/renderer/system.cpp
@@ -778,7 +778,7 @@ u32 System::DropVoices(CommandBuffer& command_buffer, u32 estimated_process_time
while (i < command_buffer.count) {
const auto node_id{cmd->node_id};
const auto node_id_type{cmd->node_id >> 28};
- const auto node_id_base{cmd->node_id & 0xFFF};
+ const auto node_id_base{(cmd->node_id >> 16) & 0xFFF};
// If the new estimated process time falls below the limit, we're done dropping.
if (estimated_process_time <= time_limit) {
diff --git a/src/audio_core/sink/cubeb_sink.cpp b/src/audio_core/sink/cubeb_sink.cpp
index 04d98a865..bbb598bc5 100644
--- a/src/audio_core/sink/cubeb_sink.cpp
+++ b/src/audio_core/sink/cubeb_sink.cpp
@@ -364,7 +364,7 @@ bool IsCubebSuitable() {
}
#endif
- // Test min latency
+ // Get min latency
cubeb_stream_params params{};
params.rate = TargetSampleRate;
params.channels = 2;
@@ -380,11 +380,6 @@ bool IsCubebSuitable() {
}
latency = std::max(latency, TargetSampleCount * 2);
- if (latency > TargetSampleCount * 3) {
- LOG_ERROR(Audio_Sink, "Cubeb latency is too high, it is not suitable.");
- return false;
- }
-
// Test opening a device with standard parameters
cubeb_devid output_device{0};
cubeb_devid input_device{0};
diff --git a/src/audio_core/sink/sink_details.cpp b/src/audio_core/sink/sink_details.cpp
index 6bec8ee7c..7c9a4e3ac 100644
--- a/src/audio_core/sink/sink_details.cpp
+++ b/src/audio_core/sink/sink_details.cpp
@@ -83,8 +83,8 @@ const SinkDetails& GetOutputSinkDetails(Settings::AudioEngine sink_id) {
break;
}
}
- LOG_ERROR(Service_Audio, "Auto-selecting the {} backend",
- Settings::CanonicalizeEnum(iter->id));
+ LOG_INFO(Service_Audio, "Auto-selecting the {} backend",
+ Settings::CanonicalizeEnum(iter->id));
} else {
if (iter != std::end(sink_details) && !iter->is_suitable()) {
LOG_ERROR(Service_Audio, "Selected backend {} is not suitable, falling back to null",
diff --git a/src/core/hle/service/audio/hwopus.cpp b/src/core/hle/service/audio/hwopus.cpp
index fa77007f3..4a8276ed1 100644
--- a/src/core/hle/service/audio/hwopus.cpp
+++ b/src/core/hle/service/audio/hwopus.cpp
@@ -174,7 +174,7 @@ public:
{6, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleavedWithPerfAndResetOld"},
{7, nullptr, "DecodeInterleavedForMultiStreamWithPerfAndResetOld"},
{8, &IHardwareOpusDecoderManager::DecodeInterleaved, "DecodeInterleaved"},
- {9, nullptr, "DecodeInterleavedForMultiStream"},
+ {9, &IHardwareOpusDecoderManager::DecodeInterleavedForMultiStream, "DecodeInterleavedForMultiStream"},
};
// clang-format on
@@ -206,6 +206,16 @@ private:
decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior);
}
+ void DecodeInterleavedForMultiStream(HLERequestContext& ctx) {
+ LOG_DEBUG(Audio, "called");
+
+ IPC::RequestParser rp{ctx};
+ const auto extra_behavior = rp.Pop<bool>() ? OpusDecoderState::ExtraBehavior::ResetContext
+ : OpusDecoderState::ExtraBehavior::None;
+
+ decoder_state.DecodeInterleaved(ctx, OpusDecoderState::PerfTime::Enabled, extra_behavior);
+ }
+
OpusDecoderState decoder_state;
};
@@ -354,6 +364,40 @@ void HwOpus::OpenHardwareOpusDecoderEx(HLERequestContext& ctx) {
system, OpusDecoderState{std::move(decoder), sample_rate, channel_count});
}
+void HwOpus::OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx) {
+ OpusMultiStreamParametersEx params;
+ std::memcpy(&params, ctx.ReadBuffer().data(), ctx.GetReadBufferSize());
+
+ const auto& sample_rate = params.sample_rate;
+ const auto& channel_count = params.channel_count;
+
+ LOG_INFO(
+ Audio,
+ "called with sample_rate={}, channel_count={}, number_streams={}, number_stereo_streams={}",
+ sample_rate, channel_count, params.number_streams, params.number_stereo_streams);
+
+ ASSERT_MSG(sample_rate == 48000 || sample_rate == 24000 || sample_rate == 16000 ||
+ sample_rate == 12000 || sample_rate == 8000,
+ "Invalid sample rate");
+
+ int error = 0;
+ OpusDecoderPtr decoder{opus_multistream_decoder_create(
+ sample_rate, static_cast<int>(channel_count), params.number_streams,
+ params.number_stereo_streams, params.channel_mappings.data(), &error)};
+ if (error != OPUS_OK || decoder == nullptr) {
+ LOG_ERROR(Audio, "Failed to create Opus decoder (error={}).", error);
+ IPC::ResponseBuilder rb{ctx, 2};
+ // TODO(ogniK): Use correct error code
+ rb.Push(ResultUnknown);
+ return;
+ }
+
+ IPC::ResponseBuilder rb{ctx, 2, 0, 1};
+ rb.Push(ResultSuccess);
+ rb.PushIpcInterface<IHardwareOpusDecoderManager>(
+ system, OpusDecoderState{std::move(decoder), sample_rate, channel_count});
+}
+
HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} {
static const FunctionInfo functions[] = {
{0, &HwOpus::OpenHardwareOpusDecoder, "OpenHardwareOpusDecoder"},
@@ -362,7 +406,8 @@ HwOpus::HwOpus(Core::System& system_) : ServiceFramework{system_, "hwopus"} {
{3, nullptr, "GetWorkBufferSizeForMultiStream"},
{4, &HwOpus::OpenHardwareOpusDecoderEx, "OpenHardwareOpusDecoderEx"},
{5, &HwOpus::GetWorkBufferSizeEx, "GetWorkBufferSizeEx"},
- {6, nullptr, "OpenHardwareOpusDecoderForMultiStreamEx"},
+ {6, &HwOpus::OpenHardwareOpusDecoderForMultiStreamEx,
+ "OpenHardwareOpusDecoderForMultiStreamEx"},
{7, &HwOpus::GetWorkBufferSizeForMultiStreamEx, "GetWorkBufferSizeForMultiStreamEx"},
{8, nullptr, "GetWorkBufferSizeExEx"},
{9, nullptr, "GetWorkBufferSizeForMultiStreamExEx"},
diff --git a/src/core/hle/service/audio/hwopus.h b/src/core/hle/service/audio/hwopus.h
index ece65c02c..91d9998ac 100644
--- a/src/core/hle/service/audio/hwopus.h
+++ b/src/core/hle/service/audio/hwopus.h
@@ -18,8 +18,10 @@ struct OpusMultiStreamParametersEx {
u32 number_stereo_streams;
u32 use_large_frame_size;
u32 padding;
- std::array<u32, 64> channel_mappings;
+ std::array<u8, 0x100> channel_mappings;
};
+static_assert(sizeof(OpusMultiStreamParametersEx) == 0x118,
+ "OpusMultiStreamParametersEx has incorrect size");
class HwOpus final : public ServiceFramework<HwOpus> {
public:
@@ -29,6 +31,7 @@ public:
private:
void OpenHardwareOpusDecoder(HLERequestContext& ctx);
void OpenHardwareOpusDecoderEx(HLERequestContext& ctx);
+ void OpenHardwareOpusDecoderForMultiStreamEx(HLERequestContext& ctx);
void GetWorkBufferSize(HLERequestContext& ctx);
void GetWorkBufferSizeEx(HLERequestContext& ctx);
void GetWorkBufferSizeForMultiStreamEx(HLERequestContext& ctx);
diff --git a/src/core/hle/service/sockets/nsd.cpp b/src/core/hle/service/sockets/nsd.cpp
index bac21752a..491b76d48 100644
--- a/src/core/hle/service/sockets/nsd.cpp
+++ b/src/core/hle/service/sockets/nsd.cpp
@@ -19,6 +19,12 @@ enum class ServerEnvironmentType : u8 {
Dp,
};
+// This is nn::nsd::EnvironmentIdentifier
+struct EnvironmentIdentifier {
+ std::array<u8, 8> identifier;
+};
+static_assert(sizeof(EnvironmentIdentifier) == 0x8);
+
NSD::NSD(Core::System& system_, const char* name) : ServiceFramework{system_, name} {
// clang-format off
static const FunctionInfo functions[] = {
@@ -101,8 +107,9 @@ void NSD::ResolveEx(HLERequestContext& ctx) {
}
void NSD::GetEnvironmentIdentifier(HLERequestContext& ctx) {
- const std::string environment_identifier = "lp1";
- ctx.WriteBuffer(environment_identifier);
+ constexpr EnvironmentIdentifier lp1 = {
+ .identifier = {'l', 'p', '1', '\0', '\0', '\0', '\0', '\0'}};
+ ctx.WriteBuffer(lp1);
IPC::ResponseBuilder rb{ctx, 2};
rb.Push(ResultSuccess);
diff --git a/src/core/hle/service/sockets/sfdnsres.cpp b/src/core/hle/service/sockets/sfdnsres.cpp
index 22e4a6f49..c657c4efd 100644
--- a/src/core/hle/service/sockets/sfdnsres.cpp
+++ b/src/core/hle/service/sockets/sfdnsres.cpp
@@ -150,6 +150,12 @@ static std::pair<u32, GetAddrInfoError> GetHostByNameRequestImpl(HLERequestConte
const std::string host = Common::StringFromBuffer(host_buffer);
// For now, ignore options, which are in input buffer 1 for GetHostByNameRequestWithOptions.
+ // Prevent resolution of Nintendo servers
+ if (host.find("srv.nintendo.net") != std::string::npos) {
+ LOG_WARNING(Network, "Resolution of hostname {} requested, returning EAI_AGAIN", host);
+ return {0, GetAddrInfoError::AGAIN};
+ }
+
auto res = Network::GetAddressInfo(host, /*service*/ std::nullopt);
if (!res.has_value()) {
return {0, Translate(res.error())};
@@ -261,6 +267,12 @@ static std::pair<u32, GetAddrInfoError> GetAddrInfoRequestImpl(HLERequestContext
const auto host_buffer = ctx.ReadBuffer(0);
const std::string host = Common::StringFromBuffer(host_buffer);
+ // Prevent resolution of Nintendo servers
+ if (host.find("srv.nintendo.net") != std::string::npos) {
+ LOG_WARNING(Network, "Resolution of hostname {} requested, returning EAI_AGAIN", host);
+ return {0, GetAddrInfoError::AGAIN};
+ }
+
std::optional<std::string> service = std::nullopt;
if (ctx.CanReadBuffer(1)) {
const std::span<const u8> service_buffer = ctx.ReadBuffer(1);
diff --git a/src/video_core/host1x/codecs/codec.cpp b/src/video_core/host1x/codecs/codec.cpp
index 220cce28a..8d7da50fc 100644
--- a/src/video_core/host1x/codecs/codec.cpp
+++ b/src/video_core/host1x/codecs/codec.cpp
@@ -319,6 +319,7 @@ void Codec::Decode() {
LOG_WARNING(Service_NVDRV, "Zero width or height in frame");
return;
}
+ bool is_interlaced = initial_frame->interlaced_frame != 0;
if (av_codec_ctx->hw_device_ctx) {
final_frame = AVFramePtr{av_frame_alloc(), AVFrameDeleter};
ASSERT_MSG(final_frame, "av_frame_alloc final_frame failed");
@@ -334,7 +335,7 @@ void Codec::Decode() {
UNIMPLEMENTED_MSG("Unexpected video format: {}", final_frame->format);
return;
}
- if (!final_frame->interlaced_frame) {
+ if (!is_interlaced) {
av_frames.push(std::move(final_frame));
} else {
if (!filters_initialized) {