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#include <cstdint>
13#include <variant>
14#include <vector>
15
16#include "absl/status/status.h"
18#include "rom/rom.h"
19
20namespace yaze {
21
23 public:
24 explicit Transaction(Rom& rom) : rom_(rom) {}
25
26 Transaction& WriteByte(int address, uint8_t value) {
27 if (!status_.ok())
28 return *this;
29 auto original = rom_.ReadByte(address);
30 if (!original.ok()) {
31 status_ = original.status();
32 return *this;
33 }
34 status_ = rom_.WriteByte(address, value);
35 if (status_.ok()) {
36 operations_.push_back({address, static_cast<uint8_t>(*original),
38 }
39 return *this;
40 }
41
42 Transaction& WriteWord(int address, uint16_t value) {
43 if (!status_.ok())
44 return *this;
45 auto original = rom_.ReadWord(address);
46 if (!original.ok()) {
47 status_ = original.status();
48 return *this;
49 }
50 status_ = rom_.WriteWord(address, value);
51 if (status_.ok()) {
52 operations_.push_back({address, static_cast<uint16_t>(*original),
54 }
55 return *this;
56 }
57
58 Transaction& WriteLong(int address, uint32_t value) {
59 if (!status_.ok())
60 return *this;
61 auto original = rom_.ReadLong(address);
62 if (!original.ok()) {
63 status_ = original.status();
64 return *this;
65 }
66 status_ = rom_.WriteLong(address, value);
67 if (status_.ok()) {
68 operations_.push_back({address, static_cast<uint32_t>(*original),
70 }
71 return *this;
72 }
73
74 Transaction& WriteVector(int address, const std::vector<uint8_t>& data) {
75 if (!status_.ok())
76 return *this;
77 auto original =
78 rom_.ReadByteVector(address, static_cast<uint32_t>(data.size()));
79 if (!original.ok()) {
80 status_ = original.status();
81 return *this;
82 }
83 status_ = rom_.WriteVector(address, data);
84 if (status_.ok()) {
85 operations_.push_back({address, *original, OperationType::kWriteVector});
86 }
87 return *this;
88 }
89
90 Transaction& WriteColor(int address, const gfx::SnesColor& color) {
91 if (!status_.ok())
92 return *this;
93 // Store original raw 16-bit value for rollback via WriteWord.
94 auto original_word = rom_.ReadWord(address);
95 if (!original_word.ok()) {
96 status_ = original_word.status();
97 return *this;
98 }
99 status_ = rom_.WriteColor(address, color);
100 if (status_.ok()) {
101 operations_.push_back({address, static_cast<uint16_t>(*original_word),
103 }
104 return *this;
105 }
106
107 absl::Status Commit() {
108 if (!status_.ok()) {
109 Rollback();
110 }
111 return status_;
112 }
113
114 void Rollback() {
115 for (auto it = operations_.rbegin(); it != operations_.rend(); ++it) {
116 const auto& op = *it;
117 switch (op.type) {
119 (void)rom_.WriteByte(op.address,
120 std::get<uint8_t>(op.original_value));
121 break;
123 (void)rom_.WriteWord(op.address,
124 std::get<uint16_t>(op.original_value));
125 break;
127 (void)rom_.WriteLong(op.address,
128 std::get<uint32_t>(op.original_value));
129 break;
131 (void)rom_.WriteVector(
132 op.address, std::get<std::vector<uint8_t>>(op.original_value));
133 break;
135 (void)rom_.WriteWord(op.address,
136 std::get<uint16_t>(op.original_value));
137 break;
138 }
139 }
140 operations_.clear();
141 }
142
143 private:
144 enum class OperationType {
150 };
151
152 struct Operation {
154 std::variant<uint8_t, uint16_t, uint32_t, std::vector<uint8_t>>
157 };
158
160 absl::Status status_;
161 std::vector<Operation> operations_;
162};
163
164} // namespace yaze
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::StatusOr< std::vector< uint8_t > > ReadByteVector(uint32_t offset, uint32_t length) const
Definition rom.cc:243
absl::Status WriteColor(uint32_t address, const gfx::SnesColor &color)
Definition rom.cc:357
absl::Status WriteByte(int addr, uint8_t value)
Definition rom.cc:286
absl::StatusOr< uint16_t > ReadWord(int offset)
Definition rom.cc:228
absl::Status WriteVector(int addr, std::vector< uint8_t > data)
Definition rom.cc:340
absl::StatusOr< uint32_t > ReadLong(int offset)
Definition rom.cc:235
absl::StatusOr< uint8_t > ReadByte(int offset)
Definition rom.cc:221
absl::Status WriteWord(int addr, uint16_t value)
Definition rom.cc:299
absl::Status WriteLong(uint32_t addr, uint32_t value)
Definition rom.cc:320
Transaction(Rom &rom)
Definition transaction.h:24
Transaction & WriteVector(int address, const std::vector< uint8_t > &data)
Definition transaction.h:74
std::vector< Operation > operations_
Transaction & WriteLong(int address, uint32_t value)
Definition transaction.h:58
Transaction & WriteWord(int address, uint16_t value)
Definition transaction.h:42
absl::Status Commit()
Transaction & WriteByte(int address, uint8_t value)
Definition transaction.h:26
absl::Status status_
Transaction & WriteColor(int address, const gfx::SnesColor &color)
Definition transaction.h:90
SNES Color container.
Definition snes_color.h:110
std::variant< uint8_t, uint16_t, uint32_t, std::vector< uint8_t > > original_value