yaze 0.3.2
Link to the Past ROM Editor
 
Loading...
Searching...
No Matches
sprite_graphics_source.h
Go to the documentation of this file.
1#ifndef YAZE_APP_EDITOR_SPRITE_SPRITE_GRAPHICS_SOURCE_H_
2#define YAZE_APP_EDITOR_SPRITE_SPRITE_GRAPHICS_SOURCE_H_
3
4#include <filesystem>
5#include <fstream>
6#include <span>
7#include <vector>
8
9#include "absl/status/statusor.h"
11#include "core/sprite_asset.h"
12#include "rom/rom.h"
13#include "zelda3/game_data.h"
14
16
17// Uses the common per-tile decoder: its exact byte requirement avoids partial
18// sheet padding and preserves all four bitplanes for custom sprite graphics.
19inline absl::StatusOr<std::vector<uint8_t>> Decode(
20 std::span<const uint8_t> bytes, int bpp) {
21 if (bpp < 2 || bpp > 4 || bytes.size() != static_cast<size_t>(64 * 8 * bpp))
22 return absl::InvalidArgumentError(
23 "A sprite graphics slot needs 64 complete 2bpp, 3bpp, or 4bpp tiles");
24 std::vector<uint8_t> pixels(4096, 0);
25 for (int tile = 0; tile < 64; ++tile) {
26 const auto decoded = gfx::UnpackBppTile(bytes, tile * 8 * bpp, bpp);
27 for (int y = 0; y < 8; ++y)
28 for (int x = 0; x < 8; ++x)
29 pixels[((tile / 16) * 8 + y) * 128 + (tile % 16) * 8 + x] =
30 decoded.data[y * 8 + x];
31 }
32 return pixels;
33}
34
35// Reads at most one slot (2048 bytes). No source is written or allocated here.
36inline absl::StatusOr<std::vector<uint8_t>> Resolve(
37 const project::SpriteGraphicsSource& source, uint16_t sheet,
38 const zelda3::GameData* data, const Rom* rom,
39 const std::filesystem::path& project_directory) {
40 if (source.kind == "sheet") {
41 if (!data || !data->sheet_store.HasSheet(sheet))
42 return absl::FailedPreconditionError(
43 "Sprite graphics sheet is unavailable in this ROM session");
44 const auto pixels = data->sheet_store.Sheet(sheet);
45 return std::vector<uint8_t>(pixels.begin(), pixels.end());
46 }
47 if (source.bpp < 2 || source.bpp > 4)
48 return absl::InvalidArgumentError(
49 "Sprite graphics depth must be 2, 3, or 4");
50 const size_t length = 64 * 8 * source.bpp;
51 if (source.kind == "raw_rom") {
52 if (!rom || !rom->is_loaded())
53 return absl::FailedPreconditionError("Load a ROM for raw ROM graphics");
54 if (source.offset > rom->size() || length > rom->size() - source.offset)
55 return absl::OutOfRangeError(
56 "Sprite graphics range extends past the ROM");
57 return Decode(
58 std::span<const uint8_t>(rom->vector().data() + source.offset, length),
59 source.bpp);
60 }
61 if (source.kind != "bin" || source.path.empty() ||
62 source.path.find('\0') != std::string::npos)
63 return absl::InvalidArgumentError("Select a BIN path or raw ROM source");
64 auto path = std::filesystem::path(source.path);
65 if (path.is_relative()) {
66 if (project_directory.empty())
67 return absl::FailedPreconditionError(
68 "Save a project or use an absolute BIN path");
69 path = project_directory / path;
70 }
71 std::error_code ec;
72 if (!std::filesystem::is_regular_file(path, ec))
73 return absl::NotFoundError(
74 "Sprite graphics BIN is missing or unreadable: " + path.string());
75 std::ifstream input(path, std::ios::binary | std::ios::ate);
76 if (!input.is_open())
77 return absl::PermissionDeniedError("Cannot open sprite graphics BIN: " +
78 path.string());
79 const auto end = input.tellg();
80 if (end < 0 || static_cast<uint64_t>(end) < source.offset ||
81 length > static_cast<uint64_t>(end) - source.offset)
82 return absl::OutOfRangeError("Sprite graphics range extends past the BIN");
83 std::vector<uint8_t> bytes(length);
84 input.seekg(source.offset);
85 if (!input.read(reinterpret_cast<char*>(bytes.data()), bytes.size()))
86 return absl::DataLossError("Could not read complete sprite graphics slot");
87 return Decode(bytes, source.bpp);
88}
89
90} // namespace yaze::editor::sprite_graphics_source
91
92#endif // YAZE_APP_EDITOR_SPRITE_SPRITE_GRAPHICS_SOURCE_H_
The Rom class is used to load, save, and modify Rom data. This is a generic SNES ROM container and do...
Definition rom.h:52
const auto & vector() const
Definition rom.h:217
auto size() const
Definition rom.h:212
bool is_loaded() const
Definition rom.h:199
bool HasSheet(uint16_t sheet) const
True when the buffer holds all 4096 bytes of sheet.
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::StatusOr< std::vector< uint8_t > > Resolve(const project::SpriteGraphicsSource &source, uint16_t sheet, const zelda3::GameData *data, const Rom *rom, const std::filesystem::path &project_directory)
absl::StatusOr< std::vector< uint8_t > > Decode(std::span< const uint8_t > bytes, int bpp)
snes_tile8 UnpackBppTile(std::span< const uint8_t > data, const uint32_t offset, const uint32_t bpp)
Definition snes_tile.cc:25