1#ifndef YAZE_ROM_WRITE_FENCE_H
2#define YAZE_ROM_WRITE_FENCE_H
12#include "absl/status/status.h"
13#include "absl/strings/str_format.h"
32 absl::Status
Allow(uint32_t start, uint32_t end, std::string_view label) {
34 return absl::InvalidArgumentError(
35 absl::StrFormat(
"WriteFence: invalid range [%u, %u)", start, end));
40 r.
label = std::string(label);
42 for (
const auto& existing :
allowed_) {
44 return absl::AlreadyExistsError(absl::StrFormat(
45 "WriteFence: range [%u, %u) overlaps existing [%u, %u) (%s)",
46 r.
start, r.
end, existing.start, existing.end,
47 existing.label.c_str()));
54 return a.start < b.start;
56 return absl::OkStatus();
59 absl::Status
Check(uint32_t start, uint32_t size,
60 std::string_view op)
const {
62 return absl::OkStatus();
64 const uint64_t end64 =
static_cast<uint64_t
>(start) + size;
65 if (end64 >
static_cast<uint64_t
>(std::numeric_limits<uint32_t>::max()) +
67 return absl::OutOfRangeError(
68 "WriteFence: write range overflows uint32");
70 const uint32_t end =
static_cast<uint32_t
>(end64);
72 if (start >= a.start && end <= a.end) {
73 return absl::OkStatus();
76 return absl::PermissionDeniedError(absl::StrFormat(
77 "ROM write fence blocked %s at [0x%06X, 0x%06X)",
78 std::string(op).c_str(), start, end));
85 const uint64_t end64 =
static_cast<uint64_t
>(start) + size;
86 if (end64 >
static_cast<uint64_t
>(std::numeric_limits<uint32_t>::max()) +
91 const uint32_t end =
static_cast<uint32_t
>(end64);
103 static bool RangesOverlap(uint32_t a_start, uint32_t a_end, uint32_t b_start,
105 return a_start < b_end && b_start < a_end;
114 std::pair<uint32_t, uint32_t> r{start, end};
115 auto it = std::lower_bound(
117 [](
const auto& a,
const auto& b) { return a.first < b.first; });
121 std::vector<std::pair<uint32_t, uint32_t>> merged;
124 if (merged.empty()) {
125 merged.push_back(cur);
128 auto& back = merged.back();
129 if (cur.first <= back.second) {
130 back.second = std::max(back.second, cur.second);
132 merged.push_back(cur);
139 std::vector<std::pair<uint32_t, uint32_t>>
written_;
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
void PushWriteFence(rom::WriteFence *fence)
void PopWriteFence(rom::WriteFence *fence)
ScopedWriteFence(const ScopedWriteFence &)=delete
ScopedWriteFence & operator=(const ScopedWriteFence &)=delete
ScopedWriteFence(Rom *rom, WriteFence *fence)
void RecordWrite(uint32_t start, uint32_t size)
std::vector< std::pair< uint32_t, uint32_t > > written_
std::vector< WriteRange > allowed_
static bool RangesOverlap(uint32_t a_start, uint32_t a_end, uint32_t b_start, uint32_t b_end)
const std::vector< std::pair< uint32_t, uint32_t > > & written_ranges() const
absl::Status Allow(uint32_t start, uint32_t end, std::string_view label)
const std::vector< WriteRange > & allowed_ranges() const
absl::Status Check(uint32_t start, uint32_t size, std::string_view op) const
void AddWrittenRange(uint32_t start, uint32_t end)