Game compat updates (#691)

* [agc] Add indirect draws

* [video] Match render target views

* [savedata] Allow dialog reinit

* [ime] Add default profile

* [GUI] update missing translations for profile box
This commit is contained in:
Berk
2026-07-29 15:59:57 +03:00
committed by GitHub
parent d5108e854d
commit 996de70f52
22 changed files with 597 additions and 18 deletions
+175
View File
@@ -0,0 +1,175 @@
// Copyright (C) 2026 SharpEmu Emulator Project
// SPDX-License-Identifier: GPL-2.0-or-later
using System;
using System.Buffers.Binary;
using System.Text;
using SharpEmu.HLE;
namespace SharpEmu.Libs.Ime;
public static class ImeDialogExports
{
private const int StatusNone = 0;
private const int StatusRunning = 1;
private const int StatusFinished = 2;
private const int EndStatusOk = 0;
private const ulong ParamMaxTextLengthOffset = 0x24;
private const ulong ParamInputTextBufferOffset = 0x28;
private const int ImeDialogErrorInvalidAddress = unchecked((int)0x80BC0001);
private const string DefaultInputText = "Sharp";
private static readonly object _gate = new();
private static int _status = StatusNone;
[SysAbiExport(
Nid = "NUeBrN7hzf0",
ExportName = "sceImeDialogInit",
Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libSceImeDialog")]
public static int ImeDialogInit(CpuContext ctx)
{
var parameterAddress = ctx[CpuRegister.Rdi];
if (parameterAddress == 0)
{
return SetReturn(ctx, ImeDialogErrorInvalidAddress);
}
TryWriteInputText(ctx, parameterAddress);
lock (_gate)
{
_status = StatusFinished;
}
return SetReturn(ctx, 0);
}
[SysAbiExport(
Nid = "IADmD4tScBY",
ExportName = "sceImeDialogGetStatus",
Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libSceImeDialog")]
public static int ImeDialogGetStatus(CpuContext ctx)
{
int status;
lock (_gate)
{
status = _status;
}
ctx[CpuRegister.Rax] = unchecked((ulong)(long)status);
return status;
}
[SysAbiExport(
Nid = "x01jxu+vxlc",
ExportName = "sceImeDialogGetResult",
Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libSceImeDialog")]
public static int ImeDialogGetResult(CpuContext ctx)
{
var resultAddress = ctx[CpuRegister.Rdi];
if (resultAddress == 0)
{
return SetReturn(ctx, ImeDialogErrorInvalidAddress);
}
Span<byte> result = stackalloc byte[8];
result.Clear();
BinaryPrimitives.WriteInt32LittleEndian(result, EndStatusOk);
ctx.Memory.TryWrite(resultAddress, result);
return SetReturn(ctx, 0);
}
[SysAbiExport(
Nid = "oBmw4xrmfKs",
ExportName = "sceImeDialogAbort",
Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libSceImeDialog")]
public static int ImeDialogAbort(CpuContext ctx)
{
lock (_gate)
{
_status = StatusFinished;
}
return SetReturn(ctx, 0);
}
[SysAbiExport(
Nid = "gyTyVn+bXMw",
ExportName = "sceImeDialogTerm",
Target = Generation.Gen4 | Generation.Gen5,
LibraryName = "libSceImeDialog")]
public static int ImeDialogTerm(CpuContext ctx)
{
lock (_gate)
{
_status = StatusNone;
}
return SetReturn(ctx, 0);
}
private static void TryWriteInputText(CpuContext ctx, ulong parameterAddress)
{
Span<byte> field = stackalloc byte[8];
if (!ctx.Memory.TryRead(parameterAddress + ParamInputTextBufferOffset, field))
{
return;
}
var bufferAddress = BinaryPrimitives.ReadUInt64LittleEndian(field);
if (bufferAddress == 0)
{
return;
}
var maxTextLength = 16u;
Span<byte> lengthField = stackalloc byte[4];
if (ctx.Memory.TryRead(parameterAddress + ParamMaxTextLengthOffset, lengthField))
{
var declared = BinaryPrimitives.ReadUInt32LittleEndian(lengthField);
if (declared is > 0 and <= 256)
{
maxTextLength = declared;
}
}
var text = Environment.GetEnvironmentVariable("SHARPEMU_DEFAULT_PROFILE");
if (string.IsNullOrEmpty(text))
{
text = DefaultInputText;
}
if ((uint)text.Length > maxTextLength)
{
text = text[..(int)maxTextLength];
}
var encoded = Encoding.Unicode.GetBytes(text);
Span<byte> payload = stackalloc byte[encoded.Length + 2];
encoded.CopyTo(payload);
payload[^2] = 0;
payload[^1] = 0;
if (ctx.Memory.TryWrite(bufferAddress, payload))
{
Console.Error.WriteLine(
$"[LOADER][WARN] ime.dialog_autofill buf=0x{bufferAddress:X16} " +
$"max={maxTextLength} text=\"{text}\"");
}
}
private static int SetReturn(CpuContext ctx, int result)
{
ctx[CpuRegister.Rax] = unchecked((ulong)(long)result);
return result;
}
}