private static IntPtr Allocate(long bytes, bool allowRetry) { IntPtr block; try { if (bytes >= largeBlockThreshold) { block = Memory.AllocateLarge((ulong)bytes); } else { block = Memory.Allocate((ulong)bytes); } } catch (OutOfMemoryException) { if (allowRetry) { Utility.GCFullCollect(); return(Allocate(bytes, false)); } else { throw; } } return(block); }
private static void init() { if (Allocation != null) { return; } Allocation = Memory.Allocate(0x90); TempPoint1 = MemoryObject.FromAddress <NiPoint3>(Allocation.Address); TempPoint2 = MemoryObject.FromAddress <NiPoint3>(Allocation.Address + 0x10); TempNormal = MemoryObject.FromAddress <NiPoint3>(Allocation.Address + 0x20); TempSafety = MemoryObject.FromAddress <NiPoint3>(Allocation.Address + 0x30); TempTransform = MemoryObject.FromAddress <NiTransform>(Allocation.Address + 0x40); TempTransform.Scale = 1.0f; TempSafety.X = 0.0f; TempSafety.Y = 0.0f; TempSafety.Z = 0.0f; SetupRaycastMask(new CollisionLayers[] { CollisionLayers.AnimStatic, CollisionLayers.Biped, CollisionLayers.CharController, //CollisionLayers.Clutter, CollisionLayers.DebrisLarge, CollisionLayers.Ground, //CollisionLayers.Props, CollisionLayers.Static, CollisionLayers.Terrain, CollisionLayers.Trap, CollisionLayers.Trees, CollisionLayers.Unidentified, }); }
internal CameraStabilize(CameraMain cameraMain, CameraTarget target) { if (cameraMain == null) { throw new ArgumentNullException("cameraMain"); } if (target == null) { throw new ArgumentNullException("target"); } this.CameraMain = cameraMain; if (Allocation == null) { Allocation = Memory.Allocate(0x60); } this.TempPoint = MemoryObject.FromAddress <NiPoint3>(Allocation.Address); this.TempTransform = MemoryObject.FromAddress <NiTransform>(Allocation.Address + 0x10); this.TempTransform.Scale = 1.0f; this.TweenPoint = MemoryObject.FromAddress <NiPoint3>(Allocation.Address + 0x50); this.ForTarget = this.GetFromTarget(target); }
private static IntPtr Allocate(long bytes, bool allowRetry) { IntPtr block; try { if (bytes >= largeBlockThreshold) { block = Memory.AllocateLarge((ulong)bytes); } else { block = Memory.Allocate((ulong)bytes); } } catch (OutOfMemoryException) { if (allowRetry) { GC.Collect(); GC.WaitForPendingFinalizers(); GC.Collect(); GC.WaitForPendingFinalizers(); return(Allocate(bytes, false)); } else { throw; } } return(block); }
public static void *Allocate(long count) { #if __x64__ return(Memory.Allocate((ulong)count)); #elif __x86__ return(Memory.Allocate((uint)count)); #endif }
internal CameraResult() { this.Allocation = Memory.Allocate(MemoryObject.SizeOf <NiTransform>()); this.Transform = MemoryObject.FromAddress <NiTransform>(this.Allocation.Address); this.Transform.Position.X = 0.0f; this.Transform.Position.Y = 0.0f; this.Transform.Position.Z = 0.0f; this.Transform.Rotation.Identity(1.0f); this.Transform.Scale = 1.0f; }
internal CameraResult() { Allocation = Memory.Allocate(0x34); Transform = MemoryObject.FromAddress <NiTransform>(Allocation.Address); Transform.Position.X = 0.0f; Transform.Position.Y = 0.0f; Transform.Position.Z = 0.0f; Transform.Rotation.Identity(1.0f); Transform.Scale = 1.0f; }
internal void Initialize() { var alloc = Memory.Allocate(0x110); alloc.Pin(); this.TargetMarkerPoint = MemoryObject.FromAddress <NiPoint3>(alloc.Address); this.TargetTeleportPoint = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x10); this.AimVectorPoint = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x20); this.SourceTeleportPoint = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x30); this.CurrentTeleportPoint = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x40); this.AimVectorPointDoubled = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x50); this.ThirdPersonTempTransform = MemoryObject.FromAddress <NiTransform>(alloc.Address + 0x60); this.SourceMovePoint = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x100); this.AimVectorPoint.X = 0.0f; this.AimVectorPoint.Z = 0.0f; this.AimVectorPoint.Y = Math.Max(100.0f, Math.Min(8000.0f, this.Plugin.Settings.MaxDistance)); this.AimVectorPointDoubled.X = 0.0f; this.AimVectorPointDoubled.Z = 0.0f; this.AimVectorPointDoubled.Y = 2000.0f + Math.Max(100.0f, Math.Min(8000.0f, this.Plugin.Settings.MaxDistance)); this.fn_Actor_SetPosition = NetScriptFramework.Main.GameInfo.GetAddressOf(36319); this.fn_BGSSoundDescriptor_PlaySound = NetScriptFramework.Main.GameInfo.GetAddressOf(32301); this.fn_TESImageSpaceModifier_Apply = NetScriptFramework.Main.GameInfo.GetAddressOf(18185); this.fn_FlashHudMeter = NetScriptFramework.Main.GameInfo.GetAddressOf(51907); this.fn_GetMagicFailedMessage = NetScriptFramework.Main.GameInfo.GetAddressOf(11295); /*var cost = this.Plugin.Settings.MagickaCost; * if (cost > 0.0f) * { * var spell = this.Plugin.Settings.SpellForm; * if (spell != null) * { * var effectItem = Memory.ReadPointer(spell.Address + 0x58); * if (effectItem != IntPtr.Zero) * { * effectItem = Memory.ReadPointer(effectItem); * if (effectItem != IntPtr.Zero) * { * var effect = MemoryObject.FromAddress<EffectSetting>(Memory.ReadPointer(effectItem + 0x10)); * if (effect != null) * Memory.WriteFloat(effect.Address + 0x6C, cost); * * Memory.WriteFloat(effectItem + 0x18, cost); * } * } * * Memory.WriteInt32(spell.Address + 0xC0, (int)(cost + 0.1f)); * } * }*/ }
private void InitMagicNode() { if (MagicNodeAllocation != null) { return; } const int count = 3; const int size = 0x130; const int size2 = 0x10; MagicNodeAllocation = Memory.Allocate(size * count + size2 * count); MagicNodes = new NiNode[count]; MagicTranslates = new NiPoint3[count]; var s = Settings.Instance; for (var i = 0; i < count; i++) { var addrOfThis = MagicNodeAllocation.Address + size * i; Memory.InvokeCdecl(Plugin.NiNode_ctor, addrOfThis, 0); MagicNodes[i] = MemoryObject.FromAddress <NiNode>(addrOfThis); MagicNodes[i].IncRef(); MagicTranslates[i] = MemoryObject.FromAddress <NiPoint3>(MagicNodeAllocation.Address + size * count + size2 * i); switch (i) { case 0: MagicTranslates[i].X = s.MagicLeftOffsetX; MagicTranslates[i].Y = s.MagicLeftOffsetY; MagicTranslates[i].Z = s.MagicLeftOffsetZ; break; case 1: MagicTranslates[i].X = s.MagicRightOffsetX; MagicTranslates[i].Y = s.MagicRightOffsetY; MagicTranslates[i].Z = s.MagicRightOffsetZ; break; case 2: MagicTranslates[i].X = s.MagicVoiceOffsetX; MagicTranslates[i].Y = s.MagicVoiceOffsetY; MagicTranslates[i].Z = s.MagicVoiceOffsetZ; break; default: MagicTranslates[i].X = 0.0f; MagicTranslates[i].Y = 0.0f; MagicTranslates[i].Z = 0.0f; break; } } }
private static void _Hook_Alchemy(CPURegisters ctx) { var menu = ctx.R13; var menuArray = menu + 280; List <TESForm> ingredients = new List <TESForm>(4); using (var alloc = Memory.Allocate(0x20)) { Memory.InvokeCdecl(fn_Alchemy1, menuArray, alloc.Address); Memory.InvokeCdecl(fn_Alchemy2, menuArray, alloc.Address + 0x10); var v96 = Memory.ReadPointer(alloc.Address); var v28 = Memory.ReadPointer(alloc.Address + 0x10); while (v28 != v96) { var v30 = Memory.ReadPointer(Memory.ReadPointer(Memory.ReadPointer(menu + 256) + 16 * Memory.ReadInt32(v96))); var item = MemoryObject.FromAddress <TESForm>(v30); ingredients.Add(item); v96 = v96 + 4; } } var potion = MemoryObject.FromAddress <MagicItem>(Memory.ReadPointer(ctx.SP + 0x50)); float skill = 5.0f; var plr = PlayerCharacter.Instance; if (plr != null) { skill = plr.GetActorValue(ActorValueIndices.Alchemy); } float xp = Formula_Alchemy(ingredients, potion, skill); if (xp < 0.0f) { xp = 0.0f; } if (Settings.DebugMode > 0) { WriteToDebugFile("Alchemy: original XP was " + ctx.XMM2f.ToString(System.Globalization.CultureInfo.InvariantCulture) + " and we replaced it with " + xp.ToString(System.Globalization.CultureInfo.InvariantCulture)); } ctx.XMM2f = xp; }
private static IntPtr AllocateString(string text) { text = text ?? ""; IntPtr addr; using (var alloc = Memory.Allocate(text.Length + 2)) { alloc.Pin(); addr = alloc.Address; Memory.WriteString(alloc.Address, text, false); Memory.WriteUInt8(alloc.Address + text.Length, 0); } return(addr); }
internal static void write_all_message(string msg) { NetScriptFramework.Main.WriteDebugMessage(msg); { var l = NetScriptFramework.Main.Log; if (l != null) { l.AppendLine(msg); } } { byte[] buf = Encoding.UTF8.GetBytes(msg.Replace("%", "%%")); using (var alloc = Memory.Allocate(buf.Length + 2)) { Memory.WriteBytes(alloc.Address, buf); Memory.WriteUInt8(alloc.Address + buf.Length, 0); Memory.InvokeCdecl(GidFileGenerationTask.addr_PrintConsole, Memory.ReadPointer(GidFileGenerationTask.addr_ConsoleSingleton), alloc.Address); } } }
private bool Process() { if (this.Cell == null) { return(false); } double pct = 0.0; if (this.Parent.TotalCellDo > 0) { pct = Math.Max(0.0, Math.Min((double)this.Parent.DidCellDo / (double)this.Parent.TotalCellDo, 1.0)) * 100.0; } string msg = "Generating grass for " + this.Parent.Name + "(" + this.X + ", " + this.Y + ") " + pct.ToString("0.##") + " pct, world " + (GidFileGenerationTask.DoneWS + 1) + " out of " + GidFileGenerationTask.TotalWS; GidFileGenerationTask.write_all_message(msg); using (var alloc = Memory.Allocate(0x20)) { Memory.WriteZero(alloc.Address, 0x20); Memory.WriteFloat(alloc.Address, this.Cell.CoordinateX * 4096.0f + 2048.0f); Memory.WriteFloat(alloc.Address + 4, this.Cell.CoordinateY * 4096.0f + 2048.0f); Memory.WriteFloat(alloc.Address + 8, 0.0f); try { Memory.InvokeCdecl(GidFileGenerationTask.addr_SetPlrTo, NetScriptFramework.SkyrimSE.PlayerCharacter.Instance.Cast <NetScriptFramework.SkyrimSE.PlayerCharacter>(), alloc.Address, alloc.Address + 0x10, this.Cell.Cast <NetScriptFramework.SkyrimSE.TESObjectCELL>(), 0); } catch { GidFileGenerationTask.KillProcess(); return(false); } } return(true); }
internal void Initialize() { if (this.Marker == null && !this.TriedToLoadMarker) { this.TriedToLoadMarker = true; NiObject.LoadFromFileAsync(new NiObjectLoadParameters() { Callback = p => { if (p.Success) { var obj = p.Result[0].As <NiAVObject>(); if (obj != null) { this.Marker = obj; this.Marker.IncRef(); this.Marker.LocalTransform.Scale = this.Plugin.Settings.MarkerScale; } } }, Count = 1, FileName = this.Plugin.Settings.MarkerNif }); } var alloc = Memory.Allocate(0x110); alloc.Pin(); this.TargetMarkerPoint = MemoryObject.FromAddress <NiPoint3>(alloc.Address); this.TargetTeleportPoint = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x10); this.AimVectorPoint = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x20); this.SourceTeleportPoint = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x30); this.CurrentTeleportPoint = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x40); this.AimVectorPointDoubled = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x50); this.ThirdPersonTempTransform = MemoryObject.FromAddress <NiTransform>(alloc.Address + 0x60); this.SourceMovePoint = MemoryObject.FromAddress <NiPoint3>(alloc.Address + 0x100); this.AimVectorPoint.X = 0.0f; this.AimVectorPoint.Z = 0.0f; this.AimVectorPoint.Y = Math.Max(100.0f, Math.Min(8000.0f, this.Plugin.Settings.MaxDistance)); this.AimVectorPointDoubled.X = 0.0f; this.AimVectorPointDoubled.Z = 0.0f; this.AimVectorPointDoubled.Y = 2000.0f + Math.Max(100.0f, Math.Min(8000.0f, this.Plugin.Settings.MaxDistance)); // Setup GameOffset - Updated PrepareFunction & InstallHook to take this value, I didn't update directly incase some use a different Offset. int GameOffset = 0x0; // Everything is based from 1_5_62 var GameVersion = NetScriptFramework.Main.Game.GameVersion; // Get the game version if (GameVersion[0] == 1 && GameVersion[1] == 5 && GameVersion[2] >= 73 && GameVersion[2] <= 97) { GameOffset = 0x1F0; // Check for game version 1_5_73 to 1_5_97, update GameOffset } var debug = CrashLog.Debug; DebugInfo.DebugFunctionInfo fn = null; if (debug == null || (fn = debug.GetFunctionInfo(36319)) == null) { throw new InvalidOperationException(this.Plugin.Name + " can't work without a debug library!"); } this.fn_Actor_SetPosition = new IntPtr(((long)(debug.BaseOffset + fn.Begin) - (uint)GameOffset)); fn = debug.GetFunctionInfo(32301); if (fn != null) { this.fn_BGSSoundDescriptor_PlaySound = new IntPtr(((long)(debug.BaseOffset + fn.Begin) - (uint)GameOffset)); } fn = debug.GetFunctionInfo(18185); if (fn != null) { this.fn_TESImageSpaceModifier_Apply = new IntPtr(((long)(debug.BaseOffset + fn.Begin) - (uint)GameOffset)); } fn = debug.GetFunctionInfo(51907); if (fn != null) { this.fn_FlashHudMeter = new IntPtr(((long)(debug.BaseOffset + fn.Begin) - (uint)GameOffset)); } fn = debug.GetFunctionInfo(11295); if (fn != null) { this.fn_GetMagicFailedMessage = new IntPtr(((long)(debug.BaseOffset + fn.Begin) - (uint)GameOffset)); } /*var cost = this.Plugin.Settings.MagickaCost; * if (cost > 0.0f) * { * var spell = this.Plugin.Settings.SpellForm; * if (spell != null) * { * var effectItem = Memory.ReadPointer(spell.Address + 0x58); * if (effectItem != IntPtr.Zero) * { * effectItem = Memory.ReadPointer(effectItem); * if (effectItem != IntPtr.Zero) * { * var effect = MemoryObject.FromAddress<EffectSetting>(Memory.ReadPointer(effectItem + 0x10)); * if (effect != null) * Memory.WriteFloat(effect.Address + 0x6C, cost); * * Memory.WriteFloat(effectItem + 0x18, cost); * } * } * * Memory.WriteInt32(spell.Address + 0xC0, (int)(cost + 0.1f)); * } * }*/ }
/// <summary> /// Implements bicubic filtering with NO bounds checking at any pixel. /// </summary> private unsafe void BicubicFitSurfaceUnchecked(Surface source, Rectangle dstRoi) { Rectangle roi = Rectangle.Intersect(dstRoi, this.Bounds); Rectangle roiIn = Rectangle.Intersect(dstRoi, new Rectangle(1, 1, width - 1, height - 1)); IntPtr rColCacheIP = Memory.Allocate(4 * (ulong)roi.Width * (ulong)sizeof(double)); double *rColCache = (double *)rColCacheIP.ToPointer(); // Precompute and then cache the value of R() for each column for (int dstX = roi.Left; dstX < roi.Right; ++dstX) { double srcColumn = (double)(dstX * (source.width - 1)) / (double)(width - 1); double srcColumnFloor = Math.Floor(srcColumn); double srcColumnFrac = srcColumn - srcColumnFloor; for (int m = -1; m <= 2; ++m) { int index = (m + 1) + ((dstX - roi.Left) * 4); double x = m - srcColumnFrac; rColCache[index] = R(x); } } // Set this up so we can cache the R()'s for every row double *rRowCache = stackalloc double[4]; for (int dstY = roi.Top; dstY < roi.Bottom; ++dstY) { double srcRow = (double)(dstY * (source.height - 1)) / (double)(height - 1); double srcRowFloor = Math.Floor(srcRow); double srcRowFrac = srcRow - srcRowFloor; int srcRowInt = (int)srcRow; ColorBgra *dstPtr = this.GetPointAddressUnchecked(roi.Left, dstY); // Compute the R() values for this row for (int n = -1; n <= 2; ++n) { double x = srcRowFrac - n; rRowCache[n + 1] = R(x); } rColCache = (double *)rColCacheIP.ToPointer(); ColorBgra *srcRowPtr = source.GetRowAddressUnchecked(srcRowInt - 1); for (int dstX = roi.Left; dstX < roi.Right; dstX++) { double srcColumn = (double)(dstX * (source.width - 1)) / (double)(width - 1); double srcColumnFloor = Math.Floor(srcColumn); double srcColumnFrac = srcColumn - srcColumnFloor; int srcColumnInt = (int)srcColumn; double blueSum = 0; double greenSum = 0; double redSum = 0; double alphaSum = 0; double totalWeight = 0; ColorBgra *srcPtr = srcRowPtr + srcColumnInt - 1; for (int n = 0; n <= 3; ++n) { double w0 = rColCache[0] * rRowCache[n]; double w1 = rColCache[1] * rRowCache[n]; double w2 = rColCache[2] * rRowCache[n]; double w3 = rColCache[3] * rRowCache[n]; double a0 = srcPtr[0].A; double a1 = srcPtr[1].A; double a2 = srcPtr[2].A; double a3 = srcPtr[3].A; alphaSum += (a0 * w0) + (a1 * w1) + (a2 * w2) + (a3 * w3); totalWeight += w0 + w1 + w2 + w3; blueSum += (a0 * srcPtr[0].B * w0) + (a1 * srcPtr[1].B * w1) + (a2 * srcPtr[2].B * w2) + (a3 * srcPtr[3].B * w3); greenSum += (a0 * srcPtr[0].G * w0) + (a1 * srcPtr[1].G * w1) + (a2 * srcPtr[2].G * w2) + (a3 * srcPtr[3].G * w3); redSum += (a0 * srcPtr[0].R * w0) + (a1 * srcPtr[1].R * w1) + (a2 * srcPtr[2].R * w2) + (a3 * srcPtr[3].R * w3); srcPtr = (ColorBgra *)((byte *)srcPtr + source.stride); } double alpha = alphaSum / totalWeight; double blue; double green; double red; if (alpha == 0) { blue = 0; green = 0; red = 0; } else { blue = blueSum / alphaSum; green = greenSum / alphaSum; red = redSum / alphaSum; // add 0.5 to ensure truncation to uint results in rounding alpha += 0.5; blue += 0.5; green += 0.5; red += 0.5; } dstPtr->Bgra = (uint)blue + ((uint)green << 8) + ((uint)red << 16) + ((uint)alpha << 24); ++dstPtr; rColCache += 4; } // for (dstX... } // for (dstY... Memory.Free(rColCacheIP); }
public static bool Launch(OptionsData options, out int index) { /* Could all seem a bit excessive just to get the pid of the client it creates? */ ProcessStartInfo startInfo = new ProcessStartInfo(); startInfo.WorkingDirectory = MainWindow.CurrentOptions.UOSFolder; startInfo.FileName = Path.Combine(MainWindow.CurrentOptions.UOSFolder, "UOSteam.exe"); index = -1; Win32.SafeProcessHandle hProcess; Win32.SafeThreadHandle hThread; uint pid, tid; int uopid = 0; UOM.SetStatusLabel("Status : Launching UOSteam"); if (Win32.CreateProcess(startInfo, true, out hProcess, out hThread, out pid, out tid)) { /* Basically rewrites a small piece of code before the client resumes to write the pid of the new client it creates, probably not portable between versions if the registers change, what can i say, I'm a noob * Never had code of old code before RazorLauncher to see how xenoglyph did it before. * Code will need to be cleaned up. */ Process p = Process.GetProcessById((int)pid); IntPtr codeAddress; IntPtr baseAddress = GetBaseAddress(hProcess, hThread); if (baseAddress == null) { UOM.SetStatusLabel("Status : UOS Hook failed"); return(false); } byte[] buffer = new byte[0x17000]; Memory.Read(hProcess.DangerousGetHandle(), (IntPtr)(((int)baseAddress) + 0x1000), buffer, true); UOM.SetStatusLabel("Status : Patching UOSteam"); /* Originally pushes hThread and hProcess on the stack before a call, we'll overwrite here. */ byte[] findBytes = new byte[] { 0x8B, 0x44, 0x24, 0x44, // MOV EAX, [ESP+44] 0x8B, 0x4C, 0x24, 0x40 // MOV ECX, [ESP+40] }; int offset = 0; if (FindSignatureOffset(findBytes, buffer, out offset)) { if ((codeAddress = Memory.Allocate(hProcess.DangerousGetHandle(), IntPtr.Zero, 1024, true)) == IntPtr.Zero) { UOM.SetStatusLabel("Status : Memory Allocation failed"); hProcess.Dispose(); hThread.Dispose(); return(false); } byte[] patchCode1 = new byte[] { 0xB8, 0x00, 0x00, 0x00, 0x00, // MOV EAX, <codeAddress> 0x8B, 0x4C, 0x24, 0x4C, // MOV ECX, [ESP+4C] 0x89, 0x08, // MOV [EAX], ECX 0xB8, 0x00, 0x00, 0x00, 0x00, // MOV EAX, <codeAddress+4> 0x8B, 0x4C, 0x24, 0x44, // MOV ECX, [ESP+4C] 0x89, 0x08, // MOV [EAX], ECX 0x8B, 0x44, 0x24, 0x48, // MOV EAX, [ESP+48] -. 0x8B, 0x4C, 0x24, 0x44, // MOV ECX, [ESP+44] -| Original code we overwrote, but esp incremented 4 due to call return address on stack 0xC3 // RETN }; patchCode1[1] = (byte)codeAddress.ToInt32(); patchCode1[2] = (byte)(codeAddress.ToInt32() >> 8); patchCode1[3] = (byte)(codeAddress.ToInt32() >> 16); patchCode1[4] = (byte)(codeAddress.ToInt32() >> 24); int codeAddress2 = (codeAddress.ToInt32() + 4); patchCode1[12] = (byte)codeAddress2; patchCode1[13] = (byte)(codeAddress2 >> 8); patchCode1[14] = (byte)(codeAddress2 >> 16); patchCode1[15] = (byte)(codeAddress2 >> 24); int patchAddress = codeAddress.ToInt32() + 8; Memory.Write(hProcess.DangerousGetHandle(), (IntPtr)patchAddress, patchCode1, true); byte[] patchCode2 = new byte[] { 0xB8, 0x00, 0x00, 0x00, 0x00, // MOV EAX, <patchAddress> 0xFF, 0xD0, // CALL EAX 0x90 // NOP }; patchCode2[1] = (byte)patchAddress; patchCode2[2] = (byte)(patchAddress >> 8); patchCode2[3] = (byte)(patchAddress >> 16); patchCode2[4] = (byte)(patchAddress >> 24); IntPtr writeAddress = new IntPtr((baseAddress.ToInt32() + 0x1000) + offset); Memory.Write(hProcess.DangerousGetHandle(), writeAddress, patchCode2, true); if (Win32.ResumeThread(hThread.DangerousGetHandle()) == -1) { UOM.SetStatusLabel("Status : ResumeThread failed"); hProcess.Dispose(); hThread.Dispose(); return(false); } // This is dodgy, to be changed to something else. byte[] uopidbytes = new byte[4]; do { Memory.Read(hProcess.DangerousGetHandle(), (IntPtr)codeAddress, uopidbytes, true); uopid = uopidbytes[3] << 24 | uopidbytes[2] << 16 | uopidbytes[1] << 8 | uopidbytes[0]; } while (uopid == 0); } hProcess.Close(); hThread.Close(); return(ClientLauncher.Attach((uint)uopid, options, true, out index)); } UOM.SetStatusLabel("Status : Process creation failed"); return(false); }
private unsafe IntPtr PSBufferNew(uint *requestedSize, uint minimumSize) { IntPtr ptr = IntPtr.Zero; try { if (requestedSize != null && *requestedSize > minimumSize) { uint allocatedSize = 0; uint size = *requestedSize; while (size > minimumSize) { // Allocate the largest buffer we can that is greater than the specified minimum size. ptr = Memory.Allocate(size, MemoryAllocationFlags.ReturnZeroOnOutOfMemory); if (ptr != IntPtr.Zero) { buffers.Add(ptr, new BufferEntry(ptr, size)); allocatedSize = size; break; } size /= 2; } if (ptr == IntPtr.Zero) { // If we cannot allocate a buffer larger than the minimum size // attempt to allocate a buffer at the minimum size. ptr = Memory.Allocate(minimumSize, MemoryAllocationFlags.ReturnZeroOnOutOfMemory); if (ptr != IntPtr.Zero) { buffers.Add(ptr, new BufferEntry(ptr, minimumSize)); allocatedSize = minimumSize; } } // The requested size pointer is used as an output parameter to return the actual number of bytes allocated. *requestedSize = allocatedSize; } else { ptr = Memory.Allocate(minimumSize, MemoryAllocationFlags.ReturnZeroOnOutOfMemory); if (ptr != IntPtr.Zero) { buffers.Add(ptr, new BufferEntry(ptr, minimumSize)); } } } catch (OutOfMemoryException) { // Free the buffer memory if the framework throws an OutOfMemoryException when adding to the buffers list. if (ptr != IntPtr.Zero) { Memory.Free(ptr); ptr = IntPtr.Zero; } } return(ptr); }
/// <summary> /// Implements bicubic filtering with bounds checking at every pixel. /// </summary> private unsafe void BicubicFitSurfaceChecked(Surface source, Rectangle dstRoi) { Rectangle roi = Rectangle.Intersect(dstRoi, this.Bounds); Rectangle roiIn = Rectangle.Intersect(dstRoi, new Rectangle(1, 1, width - 1, height - 1)); IntPtr rColCacheIP = Memory.Allocate(4 * (ulong)roi.Width * (ulong)sizeof(double)); double *rColCache = (double *)rColCacheIP.ToPointer(); // Precompute and then cache the value of R() for each column for (int dstX = roi.Left; dstX < roi.Right; ++dstX) { double srcColumn = (double)(dstX * (source.width - 1)) / (double)(width - 1); double srcColumnFloor = Math.Floor(srcColumn); double srcColumnFrac = srcColumn - srcColumnFloor; for (int m = -1; m <= 2; ++m) { int index = (m + 1) + ((dstX - roi.Left) * 4); double x = m - srcColumnFrac; rColCache[index] = R(x); } } // Set this up so we can cache the R()'s for every row double *rRowCache = stackalloc double[4]; for (int dstY = roi.Top; dstY < roi.Bottom; ++dstY) { double srcRow = (double)(dstY * (source.height - 1)) / (double)(height - 1); double srcRowFloor = (double)Math.Floor(srcRow); double srcRowFrac = srcRow - srcRowFloor; int srcRowInt = (int)srcRow; ColorBgra *dstPtr = this.GetPointAddressUnchecked(roi.Left, dstY); // Compute the R() values for this row for (int n = -1; n <= 2; ++n) { double x = srcRowFrac - n; rRowCache[n + 1] = R(x); } // See Perf Note below //int nFirst = Math.Max(-srcRowInt, -1); //int nLast = Math.Min(source.height - srcRowInt - 1, 2); for (int dstX = roi.Left; dstX < roi.Right; dstX++) { double srcColumn = (double)(dstX * (source.width - 1)) / (double)(width - 1); double srcColumnFloor = Math.Floor(srcColumn); double srcColumnFrac = srcColumn - srcColumnFloor; int srcColumnInt = (int)srcColumn; double blueSum = 0; double greenSum = 0; double redSum = 0; double alphaSum = 0; double totalWeight = 0; // See Perf Note below //int mFirst = Math.Max(-srcColumnInt, -1); //int mLast = Math.Min(source.width - srcColumnInt - 1, 2); ColorBgra *srcPtr = source.GetPointAddressUnchecked(srcColumnInt - 1, srcRowInt - 1); for (int n = -1; n <= 2; ++n) { int srcY = srcRowInt + n; for (int m = -1; m <= 2; ++m) { // Perf Note: It actually benchmarks faster on my system to do // a bounds check for every (m,n) than it is to limit the loop // to nFirst-Last and mFirst-mLast. // I'm leaving the code above, albeit commented out, so that // benchmarking between these two can still be performed. if (source.IsVisible(srcColumnInt + m, srcY)) { double w0 = rColCache[(m + 1) + (4 * (dstX - roi.Left))]; double w1 = rRowCache[n + 1]; double w = w0 * w1; blueSum += srcPtr->B * w * srcPtr->A; greenSum += srcPtr->G * w * srcPtr->A; redSum += srcPtr->R * w * srcPtr->A; alphaSum += srcPtr->A * w; totalWeight += w; } ++srcPtr; } srcPtr = (ColorBgra *)((byte *)(srcPtr - 4) + source.stride); } double alpha = alphaSum / totalWeight; double blue; double green; double red; if (alpha == 0) { blue = 0; green = 0; red = 0; } else { blue = blueSum / alphaSum; green = greenSum / alphaSum; red = redSum / alphaSum; // add 0.5 to ensure truncation to uint results in rounding alpha += 0.5; blue += 0.5; green += 0.5; red += 0.5; } dstPtr->Bgra = (uint)blue + ((uint)green << 8) + ((uint)red << 16) + ((uint)alpha << 24); ++dstPtr; } // for (dstX... } // for (dstY... Memory.Free(rColCacheIP); }
protected override bool Initialize(bool loadedAny) { this.Settings = new Settings(); this.Settings.Load(); // Maximum actor movement updates. if (this.Settings.MoverLimit != 128) { var funcAssign = NetScriptFramework.Main.GameInfo.GetAddressOf(40296, 0x90, 0, "BE"); var funcComp = NetScriptFramework.Main.GameInfo.GetAddressOf(40296, 0x9C, 0, "3D"); int defaultCap = 128; int prev = NetScriptFramework.Memory.ReadInt32(funcAssign + 1); int prev2 = NetScriptFramework.Memory.ReadInt32(funcComp + 1); if (prev != 0x80 || prev2 != 0x80) { if (prev == prev2) { NetScriptFramework.Main.Log.AppendLine("ActorLimitPlugin: Warning! Another mod may have already changed the mover limit. Expected to find " + defaultCap + " but it's " + prev + " instead. Skipping."); } else { NetScriptFramework.Main.Log.AppendLine("ActorLimitPlugin: Warning! Another mod may have already incorrectly changed the mover limit. Expected to find " + defaultCap + " but it's " + prev + " / " + prev2 + " instead. Skipping."); } return(true); } Memory.WriteInt32(funcAssign + 1, this.Settings.MoverLimit, true); Memory.WriteInt32(funcComp + 1, this.Settings.MoverLimit, true); } // Replace static buffer. if (this.Settings.ReplaceStaticBuffer) { var alloc = Memory.Allocate(0x2000); alloc.Pin(); Memory.WriteZero(alloc.Address, alloc.Size); var addr = NetScriptFramework.Main.GameInfo.GetAddressOf(40435, 0x21, 0, "48 8D 0D"); Memory.WriteHook(new HookParameters() { Address = addr, IncludeLength = 0, ReplaceLength = 7, Before = ctx => { ctx.CX = alloc.Address; }, }); addr = NetScriptFramework.Main.GameInfo.GetAddressOf(40435, 0x31, 0, "48 C1 E3 09"); Memory.WriteUInt8(addr + 3, 12, true); addr = NetScriptFramework.Main.GameInfo.GetAddressOf(40277, 0x26, 0, "48 8D 0D"); Memory.WriteHook(new HookParameters() { Address = addr, IncludeLength = 0, ReplaceLength = 7, Before = ctx => { ctx.CX = alloc.Address; } }); addr = NetScriptFramework.Main.GameInfo.GetAddressOf(40277, 0x22, 0, "48 C1 E3 09"); Memory.WriteUInt8(addr + 3, 12, true); addr = NetScriptFramework.Main.GameInfo.GetAddressOf(40427, 0x1C1, 0, "48 8D 0D"); Memory.WriteHook(new HookParameters() { Address = addr, IncludeLength = 0, ReplaceLength = 7, Before = ctx => { ctx.CX = alloc.Address; } }); addr = NetScriptFramework.Main.GameInfo.GetAddressOf(40427, 0x1BD, 0, "48 C1 E7 09"); Memory.WriteUInt8(addr + 3, 12, true); addr = NetScriptFramework.Main.GameInfo.GetAddressOf(40434, 0x61, 0, "48 8D 05"); Memory.WriteHook(new HookParameters() { Address = addr, IncludeLength = 0, ReplaceLength = 7, Before = ctx => { ctx.AX = alloc.Address; } }); addr = NetScriptFramework.Main.GameInfo.GetAddressOf(40434, 0x70, 0, "48 C1 E3 09"); Memory.WriteUInt8(addr + 3, 12, true); addr = NetScriptFramework.Main.GameInfo.GetAddressOf(40434, 0x41, 0, "83 FF 40"); var addr2 = NetScriptFramework.Main.GameInfo.GetAddressOf(40434, 0x137, 0, "48 8B 6C 24 60"); Memory.WriteHook(new HookParameters() { Address = addr, IncludeLength = 0, ReplaceLength = 9, Before = ctx => { if (ctx.DI.ToUInt32() >= 512) { ctx.IP = addr2; } } }); /*Memory.WriteHook(new HookParameters() * { * Address = new IntPtr(0x1406D2E30).FromBase(), * IncludeLength = 5, * ReplaceLength = 5, * Before = ctx => * { * NetScriptFramework.Main.WriteDebugMessage("DEBUG FUNC CALLED!"); * } * });*/ } // Maximum morph updates limit. if (this.Settings.MorphLimit != 0xA) { int want = !this.Settings.ReplaceStaticBuffer ? Math.Min(62, this.Settings.MorphLimit) : Math.Min(510, this.Settings.MorphLimit); int defaultCap = 0xA; var cap1 = NetScriptFramework.Main.GameInfo.GetAddressOf(40427, 0x1D9, 0, "BE"); int read1 = Memory.ReadInt32(cap1 + 1); var cap2 = NetScriptFramework.Main.GameInfo.GetAddressOf(507579, 8); int read2 = Memory.ReadInt32(cap2); if (read1 != defaultCap || read2 != defaultCap) { NetScriptFramework.Main.Log.AppendLine("ActorLimitPlugin: Warning! Another mod may have already changed the morph limit. Expected to find " + defaultCap + " but it's " + read1 + " / " + read2 + " instead. Skipping."); } else { Memory.WriteInt32(cap1 + 1, want, true); Memory.WriteInt32(cap2, want); } } return(true); }
private OpenResults TryToUnlockObject(Actor actor, TESObjectREFR obj) { if (_tryUnlockCounter != 1 || IsDoingOurUnlocking > 0) { Report("NoLockPicking: ERROR #1!"); return(OpenResults.Return0); } IntPtr plrPtr; IntPtr objPtr; if (actor == null || !actor.IsPlayer || obj == null || (plrPtr = actor.Cast <PlayerCharacter>()) == IntPtr.Zero || (objPtr = obj.Cast <TESObjectREFR>()) == IntPtr.Zero) { Report("NoLockPicking: ERROR #2!"); return(OpenResults.Return0); } if (cfg.OnlyWorksWhenSneaking && !actor.IsSneaking) { Memory.InvokeCdecl(this.Addr_PlaySound_Func.Value, this.Addr_LockedSound_Var.Value); return(OpenResults.Return0); } var extraLock = obj.GetLockData(true); if (extraLock == null) { Report("NoLockPicking: ERROR #3!"); return(OpenResults.Return0); } var lockData = extraLock.LockData; if (lockData == null) { Report("NoLockPicking: ERROR #4!"); return(OpenResults.Return0); } if (lockData.IsBroken) { this.ReportImpossible(); return(OpenResults.Return0); } int lockLevel = lockData.LockLevel; ExtraLockDifficultyRanks lockDifficulty = lockData.GetDifficultyRank(obj); if (lockDifficulty == ExtraLockDifficultyRanks.Impossible) { if (!cfg.AllowPickKeyDoors) { this.ReportImpossible(); return(OpenResults.Return0); } lockDifficulty = ExtraLockDifficultyRanks.VeryHard; lockLevel = 100; } bool hasSkeletonKey = false; int lockPickCount = 0; if (cfg.SuperCheatMode) { hasSkeletonKey = true; } else { var objMgr = BGSDefaultObjectManager.Instance; IntPtr mgrPtr; if (objMgr != null && (mgrPtr = objMgr.Cast <BGSDefaultObjectManager>()) != IntPtr.Zero) { if (Memory.ReadUInt8(mgrPtr + 0xB85) != 0) { var skey = Memory.ReadPointer(mgrPtr + 0x48); if (skey != IntPtr.Zero && Memory.InvokeCdecl(this.Addr_CheckItemCount_Func.Value, plrPtr, skey).ToInt32Safe() > 0) { hasSkeletonKey = true; } } } } if (!hasSkeletonKey) { var lpick = Memory.ReadPointer(this.Addr_LockPickMisc_Var.Value); if (lpick != IntPtr.Zero) { lockPickCount = Memory.InvokeCdecl(this.Addr_CheckItemCount_Func.Value, plrPtr, lpick).ToInt32Safe(); } } int requiredPicks = 0; int requiredInventoryPicks = cfg.RequireAtLeastOneLockPickInInventory ? 1 : 0; if (!hasSkeletonKey) { float mySkillMult = 1.0f; if (cfg.BonusReducesPickUsage) { using (var alloc = Memory.Allocate(0x10)) { Memory.WriteZero(alloc.Address, 0x10); Memory.WriteFloat(alloc.Address, 1.0f); Memory.InvokeCdecl(this.Addr_ApplyPerk_Func.Value, (int)PerkEntryPoints.Modify_Lockpick_Sweet_Spot, plrPtr, objPtr, alloc.Address); mySkillMult = Memory.ReadFloat(alloc.Address); } } float mySkill = actor.GetActorValue(ActorValueIndices.Lockpicking); //float mySkillExtra = actor.GetActorValue(ActorValueIndices.LockpickingMod); //float mySkillExtraPower = actor.GetActorValue(ActorValueIndices.LockpickingPowerMod); if (mySkillMult <= 0.0f) { this.ReportImpossible(); return(OpenResults.Return0); } int diffIndex = 0; { int diffDiff = (int)mySkill - lockLevel; if (diffDiff > 40) // My skill is 40+ to lock's { diffIndex = 0; } else if (diffDiff > 15) // My skill is 15+ to lock's { diffIndex = 1; } else if (diffDiff > -15) // My skill is -15 to 15 to lock's { diffIndex = 2; } else if (diffDiff > -40) // My skill is -40 to -15 to lock's { diffIndex = 3; } else { diffIndex = 4; // My skill is -40 or lower to lock's } } double cost = 0.0; switch (diffIndex) { case 0: cost = cfg.CostVeryEasy; break; case 1: cost = cfg.CostEasy; break; case 2: cost = cfg.CostMedium; break; case 3: cost = cfg.CostHard; break; case 4: cost = cfg.CostVeryHard; break; } if (cost < 0.0) { this.ReportImpossible(); return(OpenResults.Return0); } if (cost > 0.0) { float unbreakable = 0.0f; using (var alloc3 = Memory.Allocate(0x10)) { Memory.WriteFloat(alloc3.Address, 0.0f); Memory.InvokeCdecl(this.Addr_ApplyPerk_Func.Value, 0x41, plrPtr, alloc3.Address, IntPtr.Zero); unbreakable = Memory.ReadFloat(alloc3.Address); } if (unbreakable >= 0.5f) { cost = 0.0; } } if (cost > 0.0) { cost /= mySkillMult; requiredPicks = (int)cost; int maxCost = requiredPicks; cost -= requiredPicks; if (cost > 0.000001) { maxCost++; if (NetScriptFramework.Tools.Randomizer.NextDouble() < cost) { requiredPicks++; } } requiredInventoryPicks = Math.Max(requiredInventoryPicks, maxCost); } if (requiredInventoryPicks > lockPickCount || requiredPicks > lockPickCount) { this.ReportNoPicks(); return(OpenResults.Return0); } } // Take picks. if (!hasSkeletonKey && requiredPicks > 0) { actor.InvokeVTableThisCall <TESObjectREFR>(0x2B0, NetScriptFramework.Main.TrashMemory, Memory.ReadPointer(this.Addr_LockPickMisc_Var.Value), requiredPicks, 0, 0, 0, 0, 0); Memory.InvokeCdecl(this.Addr_PlaySound_Func.Value, this.Addr_PickBreakSound_Var.Value); } // Unlock object. { IsDoingOurUnlocking++; Memory.WritePointer(this.Addr_CurrentLockPickTarget_Var.Value, objPtr); Memory.WriteInt32(this.Addr_CurrentLockPickRank_Var.Value, Math.Max(0, Math.Min(4, (int)lockDifficulty))); Memory.WritePointer(this.Addr_CurrentLockPickThing_Var.Value, IntPtr.Zero); Memory.WriteUInt8(this.FakeMenu + 0x10D, 0); Memory.WriteUInt8(this.FakeMenu + 0x10B, 1); Memory.InvokeCdecl(this.Addr_ActualUnlock_Func.Value, this.FakeMenu); Memory.WritePointer(this.Addr_CurrentLockPickTarget_Var.Value, IntPtr.Zero); IsDoingOurUnlocking--; } //return OpenResults.TryOpenAgain; return(OpenResults.Return0); }
public void Start() { _processor.Start(); _memory.Allocate(); _hardDrive.Spin(); }
internal unsafe static void GetRegionScans(IntPtr hRgn, out Rectangle[] scans, out int area) { uint bytes = 0; int countdown = ScrewUpMax; int error = 0; // HACK: It seems that sometimes the GetRegionData will return ERROR_INVALID_HANDLE // even though the handle (the HRGN) is fine. Maybe the function is not // re-entrant? I'm not sure, but trying it again seems to fix it. while (countdown > 0) { bytes = SafeNativeMethods.GetRegionData(hRgn, 0, (NativeStructs.RGNDATA *)IntPtr.Zero); error = Marshal.GetLastWin32Error(); if (bytes == 0) { --countdown; System.Threading.Thread.Sleep(5); } else { break; } } // But if we retry several times and it still messes up then we will finally give up. if (bytes == 0) { throw new Win32Exception(error, "GetRegionData returned " + bytes.ToString() + ", GetLastError() = " + error.ToString()); } byte *data; // Up to 512 bytes, allocate on the stack. Otherwise allocate from the heap. if (bytes <= 512) { byte *data1 = stackalloc byte[(int)bytes]; data = data1; } else { data = (byte *)Memory.Allocate(bytes).ToPointer(); } try { var pRgnData = (NativeStructs.RGNDATA *)data; uint result = SafeNativeMethods.GetRegionData(hRgn, bytes, pRgnData); if (result != bytes) { throw new OutOfMemoryException("SafeNativeMethods.GetRegionData returned 0"); } NativeStructs.RECT *pRects = NativeStructs.RGNDATA.GetRectsPointer(pRgnData); scans = new Rectangle[pRgnData->rdh.nCount]; area = 0; for (int i = 0; i < scans.Length; ++i) { scans[i] = Rectangle.FromLTRB(pRects[i].left, pRects[i].top, pRects[i].right, pRects[i].bottom); area += scans[i].Width * scans[i].Height; } pRects = null; pRgnData = null; } finally { if (bytes > 512) { Memory.Free(new IntPtr(data)); } } }
/// <summary> /// Initializes the framework. /// </summary> internal static string Initialize() { try { // Make sure state is correct. if (Interlocked.CompareExchange(ref Status, 1, 0) != 0) { throw new InvalidOperationException("Trying to initialize the framework more than once!"); } if (GetRuntimeVersion() < RequiredRuntimeVersion) { throw new InvalidOperationException("The runtime DLL version is too old! Make sure NetScriptFramework.Runtime.dll is updated."); } // This is needed later so we can cache this call. FrameworkAssembly = System.Reflection.Assembly.GetExecutingAssembly(); // Initialize ID generator. IDGenerator = new Tools.UIDGenerator(); // Allocate trash memory. { var alloc = Memory.Allocate(1024); alloc.Pin(); TrashMemory = alloc.Address; } // Prepare and load configuration file. bool loadedConfiguration = PrepareAndLoadConfiguration(); // Initialize log file. InitializeLog(); // Setup managed unhandled exception filter. AppDomain.CurrentDomain.UnhandledException += CurrentDomain_UnhandledException; // Setup exit handler. AppDomain.CurrentDomain.ProcessExit += CurrentDomain_ProcessExit; // Write startup info. Log.AppendLine("Initializing framework version " + FrameworkVersion + "."); if (!loadedConfiguration) { Log.AppendLine("Warning: failed to load configuration file! Attempting to create a new default one."); } else { Log.AppendLine("Loaded configuration file."); } // Prepare code for .NET hooking. Memory.PrepareNETHook(); // Initialize assembly loader for plugin loading. Loader.Initialize(); // Prepare game info before loading plugins. LoadGameInfo(); // Load plugins. PluginManager.Initialize(); // Write startup info. Log.AppendLine("Finished framework initialization."); } catch (Exception ex) { if (Log != null) { Log.Append(ex); } return(ex.GetType().Name + "(" + (ex.Message ?? string.Empty) + ")"); } return(null); }
protected override bool Initialize(bool loadedAny) { cfg = new Settings(); cfg.Load(); if (!cfg.Enabled) { return(true); } this.Addr_DoorOpen_Func = CachedVid.Initialize(17521); this.Addr_DoorOpen_Hook = CachedVid.Initialize(17521, 0x313, 0, "E8 ? ? ? ? E9"); this.Addr_DoorOpen_Jmp = CachedVid.Initialize(17521, 0x65B, 0, "48 8B 9C 24 D0 01 00 00 48 81 C4 80 01 00 00"); this.Addr_ContOpen_Func = CachedVid.Initialize(17485); this.Addr_ContOpen_Hook = CachedVid.Initialize(17485, 0x1AC, 0, "E8 ? ? ? ? 32 C0"); this.Addr_CheckItemCount_Func = CachedVid.Initialize(19275); this.Addr_ImpossibleLock_Setting = CachedVid.Initialize(506405); this.Addr_OutOfLockpick_Setting = CachedVid.Initialize(506408); this.Addr_LockPickMisc_Var = CachedVid.Initialize(514921); this.Addr_ApplyPerk_Func = CachedVid.Initialize(23073); this.Addr_ActualUnlock_Func = CachedVid.Initialize(51088); this.Addr_CurrentLockPickTarget_Var = CachedVid.Initialize(519716); this.Addr_CurrentLockPickRank_Var = CachedVid.Initialize(510072); this.Addr_CurrentLockPickThing_Var = CachedVid.Initialize(519717); this.Addr_PlaySound_Func = CachedVid.Initialize(52054); this.Addr_PickBreakSound_Var = CachedVid.Initialize(269252); this.Addr_LockedSound_Var = CachedVid.Initialize(269257); { var fakealloc = Memory.Allocate(0x200); // 0x110 Memory.WriteZero(fakealloc.Address, 0x200); fakealloc.Pin(); this.FakeMenu = fakealloc.Address; } Memory.WriteHook(new HookParameters() { Address = this.Addr_DoorOpen_Hook.Value, IncludeLength = 5, ReplaceLength = 5, Before = ctx => { var actor = MemoryObject.FromAddress <Actor>(ctx.DI); var obj = MemoryObject.FromAddress <TESObjectREFR>(ctx.BX); lock (_tryUnlockLocker) { _tryUnlockCounter++; var r = TryToUnlockObject(actor, obj); switch (r) { case OpenResults.Vanilla: break; case OpenResults.Return0: ctx.Skip(); ctx.IP = this.Addr_DoorOpen_Jmp.Value; ctx.AX = IntPtr.Zero; break; case OpenResults.Return1: ctx.Skip(); ctx.IP = this.Addr_DoorOpen_Jmp.Value; ctx.AX = new IntPtr(1); break; case OpenResults.TryOpenAgain: { ctx.Skip(); ctx.IP = this.Addr_DoorOpen_Jmp.Value; var sp = ctx.SP + 0x180; IntPtr a1 = Memory.ReadPointer(sp + 0x40); IntPtr a2 = ctx.BX; IntPtr a3 = ctx.R14; IntPtr a4 = IntPtr.Zero; // Doesn't seem to be used. IntPtr a5 = IntPtr.Zero; // Not used for door? IntPtr a6 = IntPtr.Zero; // Not used for door? ctx.AX = Memory.InvokeCdecl(this.Addr_DoorOpen_Func.Value, a1, a2, a3, a4, a5, a6); } break; default: break; } _tryUnlockCounter--; } }, }); Memory.WriteHook(new HookParameters() { Address = this.Addr_ContOpen_Hook.Value, IncludeLength = 7, ReplaceLength = 7, Before = ctx => { var actor = MemoryObject.FromAddress <Actor>(ctx.DI); var obj = MemoryObject.FromAddress <TESObjectREFR>(ctx.BX); lock (_tryUnlockLocker) { _tryUnlockCounter++; var r = TryToUnlockObject(actor, obj); switch (r) { case OpenResults.Vanilla: break; case OpenResults.Return0: ctx.Skip(); ctx.AX = IntPtr.Zero; break; case OpenResults.Return1: ctx.Skip(); ctx.AX = new IntPtr(1); break; case OpenResults.TryOpenAgain: { ctx.Skip(); var sp = ctx.SP + 0x178; IntPtr a1 = ctx.R14; IntPtr a2 = ctx.BX; IntPtr a3 = ctx.DI; IntPtr a4 = IntPtr.Zero; // ? = a4 (not used?) IntPtr a5 = Memory.ReadPointer(sp + 0x28); IntPtr a6 = Memory.ReadPointer(sp + 0x30); ctx.AX = Memory.InvokeCdecl(this.Addr_ContOpen_Func.Value, a1, a2, a3, a4, a5, a6); } break; default: break; } _tryUnlockCounter--; } } }); return(true); }
internal static void FString(Tokenizer tokenizer, WordListBuilder wlbParent, StringType st = StringType.Forth) { var sbText = new StringBuilder(); var prependSpace = false; var done = false; // TODO: read tokenizer char by char to properly emulate white space while (!done) { var word = tokenizer.NextToken(); if (word.EndsWith("\"")) { done = true; word = word.Substring(0, word.Length - 1); } if (prependSpace) { sbText.Append(" "); } prependSpace = true; sbText.Append(word); } var text = sbText.ToString(); int finalValue = -1; switch (st) { case StringType.Forth: var pCountedString = Memory.Allocate(text.Length * sizeof(char) + Session.StringLengthSize); Memory.StoreCString(pCountedString, text); finalValue = pCountedString; break; case StringType.DotNet: var index = SaveManagedObject(text); finalValue = index; break; case StringType.Type: var type = Type.GetType(text); if (type == null) { throw new NfException($"Unrecognized .NET type in t\": {text}"); } if (type.IsGenericType) { var genericParameterCount = type.GetGenericArguments().Length; var parmTypes = CallAction.GetParmTypes($"Invalid types for generic type {text}", genericParameterCount); type = type.MakeGenericType(parmTypes); } finalValue = SaveManagedObject(type); break; case StringType.Stack: var pStackString = Memory.AllocateStackString(text.Length); Memory.StoreString(pStackString, text); finalValue = pStackString; break; } if (wlbParent == null) { Stack.Push(finalValue); if (st == StringType.Stack) { Stack.Push(text.Length); } } else { wlbParent.Add(new IntPrim(finalValue)); if (st == StringType.Stack) { wlbParent.Add(new IntPrim(text.Length)); } } }