freezer.h 2.8 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394
  1. // Copyright 2019 yuzu Emulator Project
  2. // Licensed under GPLv2 or any later version
  3. // Refer to the license.txt file included.
  4. #pragma once
  5. #include <atomic>
  6. #include <chrono>
  7. #include <memory>
  8. #include <mutex>
  9. #include <optional>
  10. #include <vector>
  11. #include "common/common_types.h"
  12. namespace Core::Timing {
  13. class CoreTiming;
  14. struct EventType;
  15. } // namespace Core::Timing
  16. namespace Core::Memory {
  17. class Memory;
  18. }
  19. namespace Tools {
  20. /**
  21. * This class allows the user to prevent an application from writing new values to certain memory
  22. * locations. This has a variety of uses when attempting to reverse a game.
  23. *
  24. * One example could be a cheat to prevent Mario from taking damage in SMO. One could freeze the
  25. * memory address that the game uses to store Mario's health so when he takes damage (and the game
  26. * tries to write the new health value to memory), the value won't change.
  27. */
  28. class Freezer {
  29. public:
  30. struct Entry {
  31. VAddr address;
  32. u32 width;
  33. u64 value;
  34. };
  35. explicit Freezer(Core::Timing::CoreTiming& core_timing_, Core::Memory::Memory& memory_);
  36. ~Freezer();
  37. // Enables or disables the entire memory freezer.
  38. void SetActive(bool active);
  39. // Returns whether or not the freezer is active.
  40. bool IsActive() const;
  41. // Removes all entries from the freezer.
  42. void Clear();
  43. // Freezes a value to its current memory address. The value the memory is kept at will be the
  44. // value that is read during this function. Width can be 1, 2, 4, or 8 (in bytes).
  45. u64 Freeze(VAddr address, u32 width);
  46. // Unfreezes the memory value at address. If the address isn't frozen, this is a no-op.
  47. void Unfreeze(VAddr address);
  48. // Returns whether or not the address is frozen.
  49. bool IsFrozen(VAddr address) const;
  50. // Sets the value that address should be frozen to. This doesn't change the width set by using
  51. // Freeze(). If the value isn't frozen, this will not freeze it and is thus a no-op.
  52. void SetFrozenValue(VAddr address, u64 value);
  53. // Returns the entry corresponding to the address if the address is frozen, otherwise
  54. // std::nullopt.
  55. std::optional<Entry> GetEntry(VAddr address) const;
  56. // Returns all the entries in the freezer, an empty vector means nothing is frozen.
  57. std::vector<Entry> GetEntries() const;
  58. private:
  59. using Entries = std::vector<Entry>;
  60. Entries::iterator FindEntry(VAddr address);
  61. Entries::const_iterator FindEntry(VAddr address) const;
  62. void FrameCallback(std::uintptr_t user_data, std::chrono::nanoseconds ns_late);
  63. void FillEntryReads();
  64. std::atomic_bool active{false};
  65. mutable std::mutex entries_mutex;
  66. Entries entries;
  67. std::shared_ptr<Core::Timing::EventType> event;
  68. Core::Timing::CoreTiming& core_timing;
  69. Core::Memory::Memory& memory;
  70. };
  71. } // namespace Tools