From 4bb1af93d719043f0e423742a15e29bb59048211 Mon Sep 17 00:00:00 2001 From: iExplosiveRage <120578068+iExplosiveRage@users.noreply.github.com> Date: Tue, 21 Jul 2026 02:22:51 +0300 Subject: [PATCH] SaveData: avoid invalid DeS transaction resource pointer (#480) Demon's Souls treats the small transaction-resource handle as a guest pointer during the fresh-save path. Return a null resource for the observed call shape to prevent the repeatable access violation at address 0x9. Co-authored-by: RedDv --- src/SharpEmu.Libs/SaveData/SaveDataExports.cs | 28 +++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/src/SharpEmu.Libs/SaveData/SaveDataExports.cs b/src/SharpEmu.Libs/SaveData/SaveDataExports.cs index 0496a36e..a3a9e16e 100644 --- a/src/SharpEmu.Libs/SaveData/SaveDataExports.cs +++ b/src/SharpEmu.Libs/SaveData/SaveDataExports.cs @@ -787,6 +787,34 @@ public static class SaveDataExports LibraryName = "libSceSaveData")] public static int SaveDataCreateTransactionResource(CpuContext ctx) { + // Demon's Souls first-run call: + // RDI = 0xC0000, RSI = RDX + 8, RDX = resource output. + // Writing integer handle 1 makes the title dereference [1 + 8], + // causing the repeatable access violation at guest address 0x9. + var desWorkSize = ctx[CpuRegister.Rdi]; + var desWorkAddress = ctx[CpuRegister.Rsi]; + var desResourceAddress = ctx[CpuRegister.Rdx]; + + if (desWorkSize == 0xC0000 && + desResourceAddress != 0 && + desResourceAddress <= ulong.MaxValue - sizeof(ulong) && + desWorkAddress == desResourceAddress + sizeof(ulong)) + { + if (!ctx.TryWriteUInt64(desResourceAddress, 0)) + { + return SetReturn( + ctx, + (int)OrbisGen2Result.ORBIS_GEN2_ERROR_MEMORY_FAULT); + } + + TraceSaveData( + $"create_transaction_resource_des_guard " + + $"work_size=0x{desWorkSize:X} " + + $"work=0x{desWorkAddress:X} " + + $"resource_addr=0x{desResourceAddress:X} resource=0x0"); + + return SetReturn(ctx, 0); + } var userId = unchecked((int)ctx[CpuRegister.Rdi]); var reserved = ctx[CpuRegister.Rsi];