15 nlohmann::json rows = nlohmann::json::array();
17 rows.push_back({{
"group", row.group}, {
"index", row.index}});
18 nlohmann::json result = {{
"version", 1},
19 {
"zsm_path", asset.zsm_path},
20 {
"catalog_key", asset.catalog_key},
21 {
"draw_adapter", asset.draw_adapter},
22 {
"source_path", asset.source_path},
23 {
"source_label", asset.source_label},
24 {
"source_sha256", asset.source_sha256},
25 {
"sheets", asset.sheets},
26 {
"palette_rows", rows}};
27 if (!asset.behavior.profile.empty()) {
28 result[
"version"] = 2;
31 if (std::any_of(asset.graphics_sources.begin(), asset.graphics_sources.end(),
32 [](
const auto& source) {
33 return source.kind !=
"sheet" || !source.path.empty() ||
34 source.offset != 0 || source.bpp != 3;
36 result[
"version"] = 3;
37 result[
"graphics_sources"] = nlohmann::json::array();
38 for (
const auto& source : asset.graphics_sources)
39 result[
"graphics_sources"].push_back({{
"kind", source.kind},
40 {
"path", source.path},
41 {
"offset", source.offset},
42 {
"bpp", source.bpp}});
48 const nlohmann::json& value) {
50 return absl::InvalidArgumentError(
"Invalid sprite asset binding v1");
53 if (!value.is_object() || !value.at(
"version").is_number_integer())
55 const bool graphics_version = value.at(
"version") == 3;
56 const bool has_behavior = value.contains(
"behavior");
57 if ((value.at(
"version") != 1 && value.at(
"version") != 2 &&
59 (!graphics_version && has_behavior != (value.at(
"version") == 2)) ||
60 value.size() != 9 + (has_behavior ? 1 : 0) + (graphics_version ? 1 : 0))
66 return behavior.status();
67 asset.
behavior = std::move(*behavior);
69 if (graphics_version) {
70 const auto& sources = value.at(
"graphics_sources");
71 if (!sources.is_array() || sources.size() != 8)
73 for (
size_t i = 0; i < 8; ++i) {
74 const auto& json = sources[i];
75 if (!json.is_object() || json.size() != 4 ||
76 !json.at(
"offset").is_number_integer() || json.at(
"offset") < 0 ||
77 json.at(
"offset") > std::numeric_limits<uint32_t>::max() ||
78 !json.at(
"bpp").is_number_integer() || json.at(
"bpp") < 2 ||
82 source.kind = json.at(
"kind").get<std::string>();
83 source.path = json.at(
"path").get<std::string>();
84 source.offset = json.at(
"offset").get<uint32_t>();
85 source.bpp = json.at(
"bpp").get<
int>();
86 if ((source.kind !=
"sheet" && source.kind !=
"bin" &&
87 source.kind !=
"raw_rom") ||
88 source.bpp < 2 || source.bpp > 4 || source.path.size() > 4096 ||
89 source.path.find(
'\0') != std::string::npos ||
90 (source.kind ==
"bin" && source.path.empty()) ||
91 (source.kind !=
"bin" && !source.path.empty()) ||
92 (source.kind ==
"sheet" && (source.offset || source.bpp != 3)))
96 asset.
zsm_path = value.at(
"zsm_path").get<std::string>();
97 asset.
catalog_key = value.at(
"catalog_key").get<std::string>();
98 asset.
draw_adapter = value.at(
"draw_adapter").get<std::string>();
99 asset.
source_path = value.at(
"source_path").get<std::string>();
100 asset.
source_label = value.at(
"source_label").get<std::string>();
101 asset.
source_sha256 = value.at(
"source_sha256").get<std::string>();
103 asset.
zsm_path.find(
'\0') != std::string::npos ||
115 const auto& sheets = value.at(
"sheets");
116 const auto& rows = value.at(
"palette_rows");
117 if (!sheets.is_array() || sheets.size() != 8 || !rows.is_array() ||
120 for (
size_t i = 0; i < 8; ++i) {
121 if (!sheets[i].is_number_integer() || sheets[i] < 0 || sheets[i] > 255)
123 asset.
sheets[i] = sheets[i].get<
int>();
124 if (!rows[i].is_object() || rows[i].size() != 2 ||
125 !rows[i].at(
"index").is_number_integer() || rows[i].at(
"index") < 0 ||
126 rows[i].at(
"index") > 255)
129 row.group = rows[i].at(
"group").get<std::string>();
130 row.index = rows[i].at(
"index").get<
int>();
131 if (row.group !=
"auto" && row.group !=
"global_sprites" &&
132 row.group !=
"sprites_aux1" && row.group !=
"sprites_aux2" &&
133 row.group !=
"sprites_aux3")
137 }
catch (
const nlohmann::json::exception&) {
143 const std::string& text) {
144 if (text.size() > 65536)
145 return absl::ResourceExhaustedError(
"Sprite asset binding exceeds 64 KiB");
147 std::vector<std::set<std::string>> keys;
148 auto value = nlohmann::json::parse(
149 text, [&](
int depth, nlohmann::json::parse_event_t event,
150 nlohmann::json& node) {
152 throw std::runtime_error(
"Sprite asset nesting exceeds limit");
153 if (event == nlohmann::json::parse_event_t::object_start)
155 else if (event == nlohmann::json::parse_event_t::key) {
156 if (!keys.back().insert(node.get<std::string>()).second)
157 throw std::runtime_error(
"Duplicate sprite asset field");
158 }
else if (event == nlohmann::json::parse_event_t::object_end)
163 }
catch (
const std::exception& e) {
164 return absl::InvalidArgumentError(e.what());