mirror of
https://github.com/par274/sharpemu.git
synced 2026-07-15 23:46:15 +08:00
A dozen changes; new HLEs, AV fixes, ELF loader fixes, new return codes, etc.
This commit is contained in:
@@ -0,0 +1,130 @@
|
||||
// Copyright (C) 2026 SharpEmu Emulator Project
|
||||
// SPDX-License-Identifier: GPL-2.0-or-later
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Text;
|
||||
|
||||
namespace SharpEmu.HLE;
|
||||
|
||||
public static class HleDataSymbols
|
||||
{
|
||||
private const string StackChkGuardNid = "f7uOxY9mM1U";
|
||||
private const string ProgNameNid = "djxxOmW6-aw";
|
||||
private const string LibcNeedFlagNid = "P330P3dFF68";
|
||||
private const string LibcInternalNeedFlagNid = "ZT4ODD2Ts9o";
|
||||
private const int ProgNameMaxBytes = 511;
|
||||
private const ulong StackChkGuardValue = 0xC0DEC0DECAFEBABEUL;
|
||||
|
||||
private static readonly object _gate = new();
|
||||
private static readonly nint _stackChkGuardAddress = Allocate(sizeof(ulong) * 2);
|
||||
private static readonly nint _progNameBufferAddress = Allocate(ProgNameMaxBytes + 1);
|
||||
private static readonly nint _progNamePointerAddress = Allocate(nint.Size);
|
||||
private static readonly nint _libcNeedFlagAddress = Allocate(sizeof(uint));
|
||||
private static readonly nint _libcInternalNeedFlagAddress = Allocate(sizeof(uint));
|
||||
|
||||
static HleDataSymbols()
|
||||
{
|
||||
if (_stackChkGuardAddress != 0)
|
||||
{
|
||||
Marshal.WriteInt64(_stackChkGuardAddress, unchecked((long)StackChkGuardValue));
|
||||
Marshal.WriteInt64(
|
||||
IntPtr.Add(_stackChkGuardAddress, sizeof(ulong)),
|
||||
unchecked((long)StackChkGuardValue));
|
||||
}
|
||||
|
||||
if (_libcNeedFlagAddress != 0)
|
||||
{
|
||||
Marshal.WriteInt32(_libcNeedFlagAddress, 1);
|
||||
}
|
||||
|
||||
if (_libcInternalNeedFlagAddress != 0)
|
||||
{
|
||||
Marshal.WriteInt32(_libcInternalNeedFlagAddress, 1);
|
||||
}
|
||||
|
||||
ConfigureProcessImageName("eboot.bin");
|
||||
}
|
||||
|
||||
public static IEnumerable<string> EnumerateKnownNids()
|
||||
{
|
||||
yield return StackChkGuardNid;
|
||||
yield return ProgNameNid;
|
||||
yield return LibcNeedFlagNid;
|
||||
yield return LibcInternalNeedFlagNid;
|
||||
}
|
||||
|
||||
public static void ConfigureProcessImageName(string? processImageName)
|
||||
{
|
||||
var effectiveName = string.IsNullOrWhiteSpace(processImageName)
|
||||
? "eboot.bin"
|
||||
: processImageName;
|
||||
var encodedName = Encoding.UTF8.GetBytes(effectiveName);
|
||||
var byteCount = Math.Min(encodedName.Length, ProgNameMaxBytes);
|
||||
|
||||
lock (_gate)
|
||||
{
|
||||
if (_progNameBufferAddress == 0 || _progNamePointerAddress == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
for (var i = 0; i <= ProgNameMaxBytes; i++)
|
||||
{
|
||||
Marshal.WriteByte(_progNameBufferAddress, i, 0);
|
||||
}
|
||||
|
||||
Marshal.Copy(encodedName, 0, _progNameBufferAddress, byteCount);
|
||||
WritePointer(_progNamePointerAddress, _progNameBufferAddress);
|
||||
}
|
||||
}
|
||||
|
||||
public static bool TryGetAddress(string nid, out ulong address)
|
||||
{
|
||||
var pointer = nid switch
|
||||
{
|
||||
StackChkGuardNid => _stackChkGuardAddress,
|
||||
ProgNameNid => _progNamePointerAddress,
|
||||
LibcNeedFlagNid => _libcNeedFlagAddress,
|
||||
LibcInternalNeedFlagNid => _libcInternalNeedFlagAddress,
|
||||
_ => 0,
|
||||
};
|
||||
|
||||
if (pointer == 0)
|
||||
{
|
||||
address = 0;
|
||||
return false;
|
||||
}
|
||||
|
||||
address = unchecked((ulong)pointer);
|
||||
return true;
|
||||
}
|
||||
|
||||
private static nint Allocate(int size)
|
||||
{
|
||||
try
|
||||
{
|
||||
var memory = Marshal.AllocHGlobal(size);
|
||||
for (var i = 0; i < size; i++)
|
||||
{
|
||||
Marshal.WriteByte(memory, i, 0);
|
||||
}
|
||||
|
||||
return memory;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
}
|
||||
|
||||
private static void WritePointer(nint target, nint value)
|
||||
{
|
||||
if (nint.Size == sizeof(int))
|
||||
{
|
||||
Marshal.WriteInt32(target, value.ToInt32());
|
||||
return;
|
||||
}
|
||||
|
||||
Marshal.WriteInt64(target, value.ToInt64());
|
||||
}
|
||||
}
|
||||
@@ -17,5 +17,7 @@ public interface IModuleManager
|
||||
|
||||
bool TryGetExportByName(string exportName, out ExportedFunction export);
|
||||
|
||||
bool TryDispatch(string nid, CpuContext context, out OrbisGen2Result result);
|
||||
|
||||
OrbisGen2Result Dispatch(string nid, CpuContext context);
|
||||
}
|
||||
|
||||
@@ -93,6 +93,12 @@ public sealed class ModuleManager : IModuleManager
|
||||
}
|
||||
|
||||
public OrbisGen2Result Dispatch(string nid, CpuContext context)
|
||||
{
|
||||
TryDispatch(nid, context, out var result);
|
||||
return result;
|
||||
}
|
||||
|
||||
public bool TryDispatch(string nid, CpuContext context, out OrbisGen2Result result)
|
||||
{
|
||||
ArgumentException.ThrowIfNullOrWhiteSpace(nid);
|
||||
ArgumentNullException.ThrowIfNull(context);
|
||||
@@ -100,13 +106,15 @@ public sealed class ModuleManager : IModuleManager
|
||||
if (!_dispatchTable.TryGetValue(nid, out var function) || !_exportTable.TryGetValue(nid, out var export))
|
||||
{
|
||||
context[CpuRegister.Rax] = unchecked((ulong)(int)OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND);
|
||||
return OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND;
|
||||
result = OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND;
|
||||
return false;
|
||||
}
|
||||
|
||||
if ((export.Target & context.TargetGeneration) == 0)
|
||||
{
|
||||
context[CpuRegister.Rax] = unchecked((ulong)(int)OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND);
|
||||
return OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND;
|
||||
result = OrbisGen2Result.ORBIS_GEN2_ERROR_NOT_FOUND;
|
||||
return false;
|
||||
}
|
||||
|
||||
context.ClearRaxWriteFlag();
|
||||
@@ -117,7 +125,8 @@ public sealed class ModuleManager : IModuleManager
|
||||
context[CpuRegister.Rax] = unchecked((ulong)ret);
|
||||
}
|
||||
|
||||
return (OrbisGen2Result)ret;
|
||||
result = (OrbisGen2Result)ret;
|
||||
return true;
|
||||
}
|
||||
|
||||
private static Delegate CreateHandler(Type ownerType, MethodInfo method, IDictionary<Type, object> instances)
|
||||
|
||||
@@ -45,6 +45,11 @@ public enum OrbisGen2Result : int
|
||||
/// </summary>
|
||||
ORBIS_GEN2_ERROR_BUSY = unchecked((int)0x80020010),
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the operation should be retried later.
|
||||
/// </summary>
|
||||
ORBIS_GEN2_ERROR_TRY_AGAIN = unchecked((int)0x80020023),
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that behavior is recognized but not implemented yet.
|
||||
/// </summary>
|
||||
|
||||
Reference in New Issue
Block a user