yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
transaction.h
Go to the documentation of this file.
1// Transaction helper for atomic ROM operations with rollback
2//
3// Usage:
4// yaze::Transaction tx(rom);
5// auto status = tx.WriteByte(addr, val)
6// .WriteWord(addr2, val2)
7// .Commit();
8//
9// If any write fails before Commit, subsequent operations are skipped and
10// Commit() will Rollback() previously applied writes in reverse order.
11
12#ifndef YAZE_ROM_TRANSACTION_H_
13#define YAZE_ROM_TRANSACTION_H_
14
15#include <cstdint>
16#include <string>
17#include <variant>
18#include <vector>
19
20#include "absl/status/status.h"
22#include "rom/rom.h"
23
24namespace yaze {
25
27 public:
28 explicit Transaction(Rom& rom) : rom_(rom) {}
29
30 Transaction& WriteByte(int address, uint8_t value) {
31 if (!status_.ok())
32 return *this;
33 auto original = rom_.ReadByte(address);
34 if (!original.ok()) {
35 status_ = original.status();
36 return *this;
37 }
38 status_ = rom_.WriteByte(address, value);
39 if (status_.ok()) {
40 operations_.push_back({address, static_cast<uint8_t>(*original),
42 }
43 return *this;
44 }
45
46 Transaction& WriteWord(int address, uint16_t value) {
47 if (!status_.ok())
48 return *this;
49 auto original = rom_.ReadWord(address);
50 if (!original.ok()) {
51 status_ = original.status();
52 return *this;
53 }
54 status_ = rom_.WriteWord(address, value);
55 if (status_.ok()) {
56 operations_.push_back({address, static_cast<uint16_t>(*original),
58 }
59 return *this;
60 }
61
62 Transaction& WriteLong(int address, uint32_t value) {
63 if (!status_.ok())
64 return *this;
65 auto original = rom_.ReadLong(address);
66 if (!original.ok()) {
67 status_ = original.status();
68 return *this;
69 }
70 status_ = rom_.WriteLong(address, value);
71 if (status_.ok()) {
72 operations_.push_back({address, static_cast<uint32_t>(*original),
74 }
75 return *this;
76 }
77
78 Transaction& WriteVector(int address, const std::vector<uint8_t>& data) {
79 if (!status_.ok())
80 return *this;
81 auto original =
82 rom_.ReadByteVector(address, static_cast<uint32_t>(data.size()));
83 if (!original.ok()) {
84 status_ = original.status();
85 return *this;
86 }
87 status_ = rom_.WriteVector(address, data);
88 if (status_.ok()) {
89 operations_.push_back({address, *original, OperationType::kWriteVector});
90 }
91 return *this;
92 }
93
94 Transaction& WriteColor(int address, const gfx::SnesColor& color) {
95 if (!status_.ok())
96 return *this;
97 // Store original raw 16-bit value for rollback via WriteWord.
98 auto original_word = rom_.ReadWord(address);
99 if (!original_word.ok()) {
100 status_ = original_word.status();
101 return *this;
102 }
103 status_ = rom_.WriteColor(address, color);
104 if (status_.ok()) {
105 operations_.push_back({address, static_cast<uint16_t>(*original_word),
107 }
108 return *this;
109 }
110
111 absl::Status Commit() {
112 if (!status_.ok()) {
113 Rollback();
114 }
115 return status_;
116 }
117
118 void Rollback() {
119 for (auto it = operations_.rbegin(); it != operations_.rend(); ++it) {
120 const auto& op = *it;
121 switch (op.type) {
123 (void)rom_.WriteByte(op.address,
124 std::get<uint8_t>(op.original_value));
125 break;
127 (void)rom_.WriteWord(op.address,
128 std::get<uint16_t>(op.original_value));
129 break;
131 (void)rom_.WriteLong(op.address,
132 std::get<uint32_t>(op.original_value));
133 break;
135 (void)rom_.WriteVector(
136 op.address, std::get<std::vector<uint8_t>>(op.original_value));
137 break;
139 (void)rom_.WriteWord(op.address,
140 std::get<uint16_t>(op.original_value));
141 break;
142 }
143 }
144 operations_.clear();
145 }
146
147 private:
148 enum class OperationType {
154 };
155
156 struct Operation {
158 std::variant<uint8_t, uint16_t, uint32_t, std::vector<uint8_t>>
161 };
162
164 absl::Status status_;
165 std::vector<Operation> operations_;
166};
167
168// Whole-buffer transaction used by coordinated editor saves. Individual
169// editor serializers do not share a Transaction instance and may resize the
170// ROM, so recording only writes made through Transaction is insufficient for
171// the File > Save ROM pipeline. This guard snapshots the complete in-memory
172// state and restores it unless the caller commits after the atomic disk write.
174 public:
176 : rom_(rom),
177 data_(rom.vector()),
178 filename_(rom.filename()),
179 dirty_(rom.dirty()) {}
180
183
185 if (!committed_) {
186 Rollback();
187 }
188 }
189
190 void Commit() { committed_ = true; }
191
192 void Rollback() {
193 if (committed_) {
194 return;
195 }
197 // Keep Rom::size() synchronized if a serializer resized the buffer.
198 rom_.Expand(static_cast<int>(data_.size()));
201 committed_ = true;
202 }
203
204 private:
206 std::vector<uint8_t> data_;
207 std::string filename_;
208 bool dirty_ = false;
209 bool committed_ = false;
210};
211
212} // namespace yaze
213
214#endif // YAZE_ROM_TRANSACTION_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:49
absl::StatusOr< std::vector< uint8_t > > ReadByteVector(uint32_t offset, uint32_t length) const
Definition rom.cc:808
absl::Status WriteColor(uint32_t address, const gfx::SnesColor &color)
Definition rom.cc:959
absl::Status WriteByte(int addr, uint8_t value)
Definition rom.cc:853
absl::StatusOr< uint8_t > ReadByte(int offset) const
Definition rom.cc:785
void set_dirty(bool dirty)
Definition rom.h:189
absl::Status WriteVector(int addr, std::vector< uint8_t > data)
Definition rom.cc:928
void Expand(int size)
Definition rom.h:92
absl::StatusOr< uint16_t > ReadWord(int offset) const
Definition rom.cc:793
auto & mutable_vector()
Definition rom.h:206
auto set_filename(std::string_view name)
Definition rom.h:208
absl::Status WriteWord(int addr, uint16_t value)
Definition rom.cc:873
absl::Status WriteLong(uint32_t addr, uint32_t value)
Definition rom.cc:901
absl::StatusOr< uint32_t > ReadLong(int offset) const
Definition rom.cc:800
ScopedRomTransaction(const ScopedRomTransaction &)=delete
std::vector< uint8_t > data_
ScopedRomTransaction & operator=(const ScopedRomTransaction &)=delete
Transaction(Rom &rom)
Definition transaction.h:28
Transaction & WriteVector(int address, const std::vector< uint8_t > &data)
Definition transaction.h:78
std::vector< Operation > operations_
Transaction & WriteLong(int address, uint32_t value)
Definition transaction.h:62
Transaction & WriteWord(int address, uint16_t value)
Definition transaction.h:46
absl::Status Commit()
Transaction & WriteByte(int address, uint8_t value)
Definition transaction.h:30
absl::Status status_
Transaction & WriteColor(int address, const gfx::SnesColor &color)
Definition transaction.h:94
SNES Color container.
Definition snes_color.h:110
std::variant< uint8_t, uint16_t, uint32_t, std::vector< uint8_t > > original_value