yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
save_state_manager.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EMU_RENDER_SAVE_STATE_MANAGER_H_
2#define YAZE_APP_EMU_RENDER_SAVE_STATE_MANAGER_H_
3
4#include <cstdint>
5#include <memory>
6#include <string>
7#include <unordered_map>
8
9#include "absl/status/status.h"
10#include "absl/status/statusor.h"
12
13namespace yaze {
14
15class Rom;
16
17namespace emu {
18class Snes;
19} // namespace emu
20
21namespace emu {
22namespace render {
23
24// Manages save states for the emulator render service.
25//
26// This class handles:
27// 1. Loading pre-generated baseline states (shipped with yaze)
28// 2. Generating new states via TAS-style game boot
29// 3. Verifying ROM compatibility via checksum
30// 4. Caching states for reuse
31//
32// The save state approach allows rendering of objects/sprites by loading
33// a known "game ready" state and injecting the specific entity data,
34// avoiding the "cold start" problem where handlers expect full game context.
36 public:
37 SaveStateManager(emu::Snes* snes, Rom* rom);
39
40 // Initialize the manager (checks for existing states, calculates ROM checksum)
41 absl::Status Initialize();
42
43 // Load a baseline state of the given type
44 // If context_id is provided, loads state for specific room/area
45 absl::Status LoadState(StateType type, int context_id = 0);
46
47 // Generate a new state by booting the game to the specified room
48 // This is slow (~5-30 seconds) as it runs the game via TAS input
49 absl::Status GenerateRoomState(int room_id);
50
51 // Generate all baseline states
52 absl::Status GenerateAllBaselineStates();
53
54 // Check if a cached state exists for the given type/context
55 bool HasCachedState(StateType type, int context_id = 0) const;
56
57 // Get metadata for a cached state
58 absl::StatusOr<StateMetadata> GetStateMetadata(StateType type,
59 int context_id = 0) const;
60
61 // Save current SNES state to a file
62 absl::Status SaveStateToFile(const std::string& path,
63 const StateMetadata& metadata);
64
65 // Load SNES state from a file
66 absl::Status LoadStateFromFile(const std::string& path);
67
68 // Get/set the base directory for state files
69 void SetStateDirectory(const std::string& path) { state_directory_ = path; }
70 const std::string& GetStateDirectory() const { return state_directory_; }
71
72 // Calculate CRC32 checksum of ROM
73 uint32_t CalculateRomChecksum() const;
74
75 private:
76 // TAS-style game boot helpers
77 absl::Status BootToTitleScreen();
78 absl::Status NavigateToFileSelect();
79 absl::Status StartNewGame();
80 absl::Status NavigateToRoom(int room_id);
81
82 // Input injection
83 void PressButton(int button, int frames = 1);
84 void ReleaseAllButtons();
85 void WaitFrames(int frames);
86
87 // Module waiting helpers
88 bool WaitForModule(uint8_t target, int max_frames);
89 absl::Status TeleportToRoomViaWram(int room_id);
90 absl::Status NavigateToRoomViaTas(int room_id);
91
92 // WRAM monitoring
93 uint8_t ReadWram(uint32_t addr);
94 uint16_t ReadWram16(uint32_t addr);
95 int GetCurrentRoom();
96 uint8_t GetGameModule();
97 bool IsRoomFullyLoaded();
98
99 // State file path generation
100 std::string GetStatePath(StateType type, int context_id) const;
101 std::string GetMetadataPath(StateType type, int context_id) const;
102
103 // Verify state compatibility with current ROM
104 bool IsStateCompatible(const StateMetadata& metadata) const;
105
106 emu::Snes* snes_ = nullptr;
107 Rom* rom_ = nullptr;
108
109 std::string state_directory_;
110 uint32_t rom_checksum_ = 0;
111
112 // Cache of loaded state metadata
113 struct CacheKey {
116 bool operator==(const CacheKey& other) const {
117 return type == other.type && context_id == other.context_id;
118 }
119 };
121 size_t operator()(const CacheKey& k) const {
122 return std::hash<int>()(static_cast<int>(k.type)) ^
123 (std::hash<int>()(k.context_id) << 1);
124 }
125 };
126 std::unordered_map<CacheKey, StateMetadata, CacheKeyHash> state_cache_;
127};
128
129// Button constants for input injection (SNES controller bit indices)
130// These map to Snes::SetButtonState() which expects bit indices 0-11
131namespace buttons {
132constexpr int kB = 0; // Bit 0
133constexpr int kY = 1; // Bit 1
134constexpr int kSelect = 2; // Bit 2
135constexpr int kStart = 3; // Bit 3
136constexpr int kUp = 4; // Bit 4
137constexpr int kDown = 5; // Bit 5
138constexpr int kLeft = 6; // Bit 6
139constexpr int kRight = 7; // Bit 7
140constexpr int kA = 8; // Bit 8
141constexpr int kX = 9; // Bit 9
142constexpr int kL = 10; // Bit 10
143constexpr int kR = 11; // Bit 11
144} // namespace buttons
145
146} // namespace render
147} // namespace emu
148} // namespace yaze
149
150#endif // YAZE_APP_EMU_RENDER_SAVE_STATE_MANAGER_H_
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:24
absl::Status GenerateRoomState(int room_id)
bool HasCachedState(StateType type, int context_id=0) const
bool IsStateCompatible(const StateMetadata &metadata) const
const std::string & GetStateDirectory() const
SaveStateManager(emu::Snes *snes, Rom *rom)
std::string GetStatePath(StateType type, int context_id) const
absl::Status LoadState(StateType type, int context_id=0)
std::unordered_map< CacheKey, StateMetadata, CacheKeyHash > state_cache_
void PressButton(int button, int frames=1)
absl::Status LoadStateFromFile(const std::string &path)
void SetStateDirectory(const std::string &path)
absl::StatusOr< StateMetadata > GetStateMetadata(StateType type, int context_id=0) const
bool WaitForModule(uint8_t target, int max_frames)
absl::Status TeleportToRoomViaWram(int room_id)
absl::Status NavigateToRoomViaTas(int room_id)
std::string GetMetadataPath(StateType type, int context_id) const
absl::Status SaveStateToFile(const std::string &path, const StateMetadata &metadata)
absl::Status NavigateToRoom(int room_id)
bool operator==(const CacheKey &other) const