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 "app/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()) return *this;
28 auto original = rom_.ReadByte(address);
29 if (!original.ok()) {
30 status_ = original.status();
31 return *this;
32 }
33 status_ = rom_.WriteByte(address, value);
34 if (status_.ok()) {
35 operations_.push_back({address, static_cast<uint8_t>(*original), OperationType::kWriteByte});
36 }
37 return *this;
38 }
39
40 Transaction &WriteWord(int address, uint16_t value) {
41 if (!status_.ok()) return *this;
42 auto original = rom_.ReadWord(address);
43 if (!original.ok()) {
44 status_ = original.status();
45 return *this;
46 }
47 status_ = rom_.WriteWord(address, value);
48 if (status_.ok()) {
49 operations_.push_back({address, static_cast<uint16_t>(*original), OperationType::kWriteWord});
50 }
51 return *this;
52 }
53
54 Transaction &WriteLong(int address, uint32_t value) {
55 if (!status_.ok()) return *this;
56 auto original = rom_.ReadLong(address);
57 if (!original.ok()) {
58 status_ = original.status();
59 return *this;
60 }
61 status_ = rom_.WriteLong(address, value);
62 if (status_.ok()) {
63 operations_.push_back({address, static_cast<uint32_t>(*original), OperationType::kWriteLong});
64 }
65 return *this;
66 }
67
68 Transaction &WriteVector(int address, const std::vector<uint8_t> &data) {
69 if (!status_.ok()) return *this;
70 auto original = rom_.ReadByteVector(address, static_cast<uint32_t>(data.size()));
71 if (!original.ok()) {
72 status_ = original.status();
73 return *this;
74 }
75 status_ = rom_.WriteVector(address, data);
76 if (status_.ok()) {
77 operations_.push_back({address, *original, OperationType::kWriteVector});
78 }
79 return *this;
80 }
81
82 Transaction &WriteColor(int address, const gfx::SnesColor &color) {
83 if (!status_.ok()) return *this;
84 // Store original raw 16-bit value for rollback via WriteWord.
85 auto original_word = rom_.ReadWord(address);
86 if (!original_word.ok()) {
87 status_ = original_word.status();
88 return *this;
89 }
90 status_ = rom_.WriteColor(address, color);
91 if (status_.ok()) {
92 operations_.push_back({address, static_cast<uint16_t>(*original_word), OperationType::kWriteColor});
93 }
94 return *this;
95 }
96
97 absl::Status Commit() {
98 if (!status_.ok()) {
99 Rollback();
100 }
101 return status_;
102 }
103
104 void Rollback() {
105 for (auto it = operations_.rbegin(); it != operations_.rend(); ++it) {
106 const auto &op = *it;
107 switch (op.type) {
109 (void)rom_.WriteByte(op.address, std::get<uint8_t>(op.original_value));
110 break;
112 (void)rom_.WriteWord(op.address, std::get<uint16_t>(op.original_value));
113 break;
115 (void)rom_.WriteLong(op.address, std::get<uint32_t>(op.original_value));
116 break;
118 (void)rom_.WriteVector(op.address, std::get<std::vector<uint8_t>>(op.original_value));
119 break;
121 (void)rom_.WriteWord(op.address, std::get<uint16_t>(op.original_value));
122 break;
123 }
124 }
125 operations_.clear();
126 }
127
128 private:
130
131 struct Operation {
133 std::variant<uint8_t, uint16_t, uint32_t, std::vector<uint8_t>> original_value;
135 };
136
138 absl::Status status_;
139 std::vector<Operation> operations_;
140};
141
142} // namespace yaze
The Rom class is used to load, save, and modify Rom data.
Definition rom.h:74
absl::StatusOr< std::vector< uint8_t > > ReadByteVector(uint32_t offset, uint32_t length) const
Definition rom.cc:685
absl::Status WriteColor(uint32_t address, const gfx::SnesColor &color)
Definition rom.cc:795
absl::Status WriteByte(int addr, uint8_t value)
Definition rom.cc:728
absl::StatusOr< uint16_t > ReadWord(int offset)
Definition rom.cc:668
absl::Status WriteVector(int addr, std::vector< uint8_t > data)
Definition rom.cc:780
absl::StatusOr< uint32_t > ReadLong(int offset)
Definition rom.cc:676
absl::StatusOr< uint8_t > ReadByte(int offset)
Definition rom.cc:661
absl::Status WriteWord(int addr, uint16_t value)
Definition rom.cc:740
absl::Status WriteLong(uint32_t addr, uint32_t value)
Definition rom.cc:766
Transaction(Rom &rom)
Definition transaction.h:24
Transaction & WriteVector(int address, const std::vector< uint8_t > &data)
Definition transaction.h:68
std::vector< Operation > operations_
Transaction & WriteLong(int address, uint32_t value)
Definition transaction.h:54
Transaction & WriteWord(int address, uint16_t value)
Definition transaction.h:40
absl::Status Commit()
Definition transaction.h:97
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:82
SNES Color container.
Definition snes_color.h:109
Main namespace for the application.
Definition controller.cc:20
std::variant< uint8_t, uint16_t, uint32_t, std::vector< uint8_t > > original_value