yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
graphics_sheet_store.cc
Go to the documentation of this file.
2
3#include <algorithm>
4#include <atomic>
5
6#include "absl/strings/str_format.h"
7
8namespace yaze {
9namespace zelda3 {
10
11namespace {
12
13uint64_t NextRevision() {
14 static std::atomic<uint64_t> counter{0};
15 return ++counter;
16}
17
18} // namespace
19
20bool GraphicsSheetStore::HasSheet(uint16_t sheet) const {
21 return sheet < kSheetCount &&
22 (static_cast<size_t>(sheet) + 1) * kSheetBytes <= pixels_.size();
23}
24
25absl::Span<const uint8_t> GraphicsSheetStore::Sheet(uint16_t sheet) const {
26 if (!HasSheet(sheet)) {
27 return {};
28 }
29 return absl::MakeConstSpan(pixels_.data() + sheet * kSheetBytes, kSheetBytes);
30}
31
32uint64_t GraphicsSheetStore::Revision(uint16_t sheet) const {
33 return sheet < kSheetCount ? revisions_[sheet] : 0;
34}
35
36absl::Status GraphicsSheetStore::WriteSheet(uint16_t sheet,
37 absl::Span<const uint8_t> pixels,
38 uint8_t max_index) {
39 if (!HasSheet(sheet)) {
40 return absl::OutOfRangeError(absl::StrFormat(
41 "Sheet 0x%02X is not in the graphics store (%zu bytes held)", sheet,
42 pixels_.size()));
43 }
44 if (pixels.size() != kSheetBytes) {
45 return absl::InvalidArgumentError(
46 absl::StrFormat("Sheet 0x%02X needs %zu pixels, got %zu", sheet,
47 kSheetBytes, pixels.size()));
48 }
49 const auto high =
50 std::find_if(pixels.begin(), pixels.end(),
51 [max_index](uint8_t v) { return v > max_index; });
52 if (high != pixels.end()) {
53 const size_t at = static_cast<size_t>(high - pixels.begin());
54 return absl::InvalidArgumentError(absl::StrFormat(
55 "Sheet 0x%02X pixel (%zu, %zu) uses color %d; the limit is %d", sheet,
56 at % kSheetWidth, at / kSheetWidth, *high, max_index));
57 }
58 auto first = pixels_.begin() + sheet * kSheetBytes;
59 if (std::equal(pixels.begin(), pixels.end(), first)) {
60 return absl::OkStatus();
61 }
62 std::copy(pixels.begin(), pixels.end(), first);
63 revisions_[sheet] = NextRevision();
64 return absl::OkStatus();
65}
66
68 for (auto& revision : revisions_) {
69 revision = NextRevision();
70 }
71}
72
77
79 : sheet_(sheet) {
80 if (!store.HasSheet(sheet)) {
81 return;
82 }
83 store_ = &store;
84 const auto current = store.Sheet(sheet);
85 before_.assign(current.begin(), current.end());
86}
87
91
92uint8_t GraphicsSheetStore::Edit::Get(int x, int y) const {
93 if (!ok() || x < 0 || y < 0 || x >= width() || y >= height()) {
94 return 0;
95 }
96 return store_->pixels_[sheet_ * kSheetBytes + y * kSheetWidth + x];
97}
98
99bool GraphicsSheetStore::Edit::Set(int x, int y, uint8_t index) {
100 if (!ok() || x < 0 || y < 0 || x >= width() || y >= height()) {
101 return false;
102 }
103 uint8_t& pixel = store_->pixels_[sheet_ * kSheetBytes + y * kSheetWidth + x];
104 if (pixel == index) {
105 return false;
106 }
107 pixel = index;
108 uncommitted_ = true;
109 return true;
110}
111
112absl::Span<const uint8_t> GraphicsSheetStore::Edit::pixels() const {
113 return ok() ? store_->Sheet(sheet_) : absl::Span<const uint8_t>();
114}
115
117 if (!ok() || !uncommitted_) {
118 return;
119 }
120 store_->revisions_[sheet_] = NextRevision();
121 uncommitted_ = false;
122}
123
124} // namespace zelda3
125} // namespace yaze
void Commit()
Bumps the revision once if any pixel changed since the last commit.
bool Set(int x, int y, uint8_t index)
Edit(GraphicsSheetStore &store, uint16_t sheet)
ok() is false when store does not hold sheet.
absl::Span< const uint8_t > pixels() const
The sheet now, including uncommitted pixels.
uint8_t Get(int x, int y) const
The pixel at (x, y), or 0 outside the sheet.
void MarkAllSheetsChanged()
Call after the loader refills the buffer: bumps every revision.
bool HasSheet(uint16_t sheet) const
True when the buffer holds all 4096 bytes of sheet.
void Clear()
Empties the buffer and bumps every revision.
const std::vector< uint8_t > & pixels() const
uint64_t Revision(uint16_t sheet) const
static constexpr uint16_t kSheetCount
std::array< uint64_t, kSheetCount > revisions_
absl::Span< const uint8_t > Sheet(uint16_t sheet) const
The sheet's 4096 pixels, or an empty span when it is not held.
absl::Status WriteSheet(uint16_t sheet, absl::Span< const uint8_t > pixels, uint8_t max_index=0x0F)
One ROM session's graphics sheet pixels, with a revision per sheet.