mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-22 10:56:20 +08:00
[VideoOut] Initialize output options storage (#315)
* [VideoOut] Initialize output options storage * [VideoOut] Keep output options size local
This commit is contained in:
@@ -381,7 +381,18 @@ public static class VideoOutExports
|
||||
LibraryName = "libSceVideoOut")]
|
||||
public static int VideoOutInitializeOutputOptions(CpuContext ctx)
|
||||
{
|
||||
return (int)OrbisGen2Result.ORBIS_GEN2_OK;
|
||||
const int outputOptionsSize = 0x40;
|
||||
var optionsAddress = ctx[CpuRegister.Rdi];
|
||||
if (optionsAddress == 0)
|
||||
{
|
||||
return OrbisVideoOutErrorInvalidAddress;
|
||||
}
|
||||
|
||||
Span<byte> options = stackalloc byte[outputOptionsSize];
|
||||
options.Clear();
|
||||
return ctx.Memory.TryWrite(optionsAddress, options)
|
||||
? (int)OrbisGen2Result.ORBIS_GEN2_OK
|
||||
: (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT;
|
||||
}
|
||||
|
||||
[SysAbiExport(
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2026 SharpEmu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
using SharpEmu.HLE;
|
||||
using SharpEmu.Libs.VideoOut;
|
||||
using Xunit;
|
||||
|
||||
namespace SharpEmu.Libs.Tests.VideoOut;
|
||||
|
||||
public sealed class VideoOutOutputOptionsTests
|
||||
{
|
||||
private const ulong MemoryBase = 0x1_0000_0000;
|
||||
private const ulong OptionsAddress = MemoryBase + 0x40;
|
||||
private const int OptionsSize = 0x40;
|
||||
private const int InvalidAddress = unchecked((int)0x80290002);
|
||||
|
||||
[Theory]
|
||||
[InlineData(Generation.Gen4)]
|
||||
[InlineData(Generation.Gen5)]
|
||||
public void InitializeOutputOptions_ClearsExactlyOneStructure(Generation generation)
|
||||
{
|
||||
var memory = new FakeCpuMemory(MemoryBase, 0x1000);
|
||||
var context = new CpuContext(memory, generation);
|
||||
var sentinel = new byte[OptionsSize + 1];
|
||||
Array.Fill(sentinel, (byte)0xCC);
|
||||
Assert.True(memory.TryWrite(OptionsAddress, sentinel));
|
||||
context[CpuRegister.Rdi] = OptionsAddress;
|
||||
|
||||
Assert.Equal(0, VideoOutExports.VideoOutInitializeOutputOptions(context));
|
||||
|
||||
var result = new byte[OptionsSize + 1];
|
||||
Assert.True(memory.TryRead(OptionsAddress, result));
|
||||
Assert.All(result.AsSpan(0, OptionsSize).ToArray(), value => Assert.Equal(0, value));
|
||||
Assert.Equal(0xCC, result[OptionsSize]);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InitializeOutputOptions_NullAddressReturnsInvalidAddress()
|
||||
{
|
||||
var context = new CpuContext(new FakeCpuMemory(MemoryBase, 0x100), Generation.Gen5);
|
||||
context[CpuRegister.Rdi] = 0;
|
||||
|
||||
Assert.Equal(InvalidAddress, VideoOutExports.VideoOutInitializeOutputOptions(context));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void InitializeOutputOptions_UnwritableStructureReturnsMemoryFault()
|
||||
{
|
||||
var context = new CpuContext(new FakeCpuMemory(MemoryBase, 0x100), Generation.Gen5);
|
||||
context[CpuRegister.Rdi] = MemoryBase + 0xC1;
|
||||
|
||||
Assert.Equal(
|
||||
(int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT,
|
||||
VideoOutExports.VideoOutInitializeOutputOptions(context));
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user