yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
graphics_preview.h
Go to the documentation of this file.
1#ifndef YAZE_ZELDA3_OVERWORLD_GRAPHICS_PREVIEW_H_
2#define YAZE_ZELDA3_OVERWORLD_GRAPHICS_PREVIEW_H_
3
4#include <array>
5#include <cstdint>
6#include <map>
7#include <span>
8#include <vector>
9
10#include "absl/status/status.h"
11#include "absl/status/statusor.h"
12
13namespace yaze::zelda3 {
14
15using PreviewTile8 = std::array<uint8_t, 64>;
16using AreaGraphicsPreview = std::map<uint16_t, PreviewTile8>;
17using OverworldGraphicsPreview = std::map<int, AreaGraphicsPreview>;
18
19// Decode raw SNES 4bpp DMA bytes into BG character IDs. VRAM addresses are
20// words; character data is 32 bytes per tile. No ROM or shared sheet is changed.
21inline absl::StatusOr<AreaGraphicsPreview> DecodeGraphicsPreviewTransfer(
22 std::span<const uint8_t> bytes, int destination_word, int bg_base_word) {
23 if (bg_base_word < 0 || bg_base_word > 0x4000 || destination_word < 0 ||
24 destination_word > 0x7FFF) {
25 return absl::InvalidArgumentError("Preview VRAM word address out of range");
26 }
27 const int offset = (destination_word - bg_base_word) * 2;
28 if (offset < 0 || offset % 32 != 0 || bytes.empty() ||
29 bytes.size() % 32 != 0 || bytes.size() > 0x8000 ||
30 static_cast<size_t>(offset) + bytes.size() > 0x8000 ||
31 destination_word * 2 + bytes.size() > 0x10000) {
32 return absl::InvalidArgumentError(
33 "Preview DMA must contain aligned 4bpp BG characters within VRAM");
34 }
36 for (size_t tile = 0; tile < bytes.size() / 32; ++tile) {
37 PreviewTile8 pixels{};
38 for (int y = 0; y < 8; ++y) {
39 for (int x = 0; x < 8; ++x) {
40 for (int plane = 0; plane < 4; ++plane) {
41 const size_t source =
42 tile * 32 + (plane / 2) * 16 + y * 2 + plane % 2;
43 pixels[y * 8 + x] |= ((bytes[source] >> (7 - x)) & 1) << plane;
44 }
45 }
46 }
47 result.emplace(static_cast<uint16_t>(offset / 32 + tile), pixels);
48 }
49 return result;
50}
51
52inline void ApplyGraphicsPreview(const AreaGraphicsPreview& preview,
53 std::vector<uint8_t>& graphics) {
54 constexpr int kWidth = 128;
55 for (const auto& [id, pixels] : preview) {
56 const size_t origin = (id / 16 * 8) * kWidth + (id % 16) * 8;
57 if (origin + 7 * kWidth + 8 > graphics.size())
58 continue;
59 for (int y = 0; y < 8; ++y) {
60 for (int x = 0; x < 8; ++x)
61 graphics[origin + y * kWidth + x] = pixels[y * 8 + x];
62 }
63 }
64}
65
66} // namespace yaze::zelda3
67#endif
Zelda 3 specific classes and functions.
std::map< uint16_t, PreviewTile8 > AreaGraphicsPreview
absl::StatusOr< AreaGraphicsPreview > DecodeGraphicsPreviewTransfer(std::span< const uint8_t > bytes, int destination_word, int bg_base_word)
void ApplyGraphicsPreview(const AreaGraphicsPreview &preview, std::vector< uint8_t > &graphics)
std::array< uint8_t, 64 > PreviewTile8
std::map< int, AreaGraphicsPreview > OverworldGraphicsPreview