8#include "fruit/fruit.h"
58 :
Command{parent_app, kCommandName, kCommandDesc, kCommandGroup}
61 cmd.add_option(
"<tileset-name>", tileset_name_,
"Name of the tileset to decompile")->required();
71 const bool no_color = !isatty(STDERR_FILENO);
72 fruit::Injector injector{di::get_formatter_component, no_color};
76 auto stderr_diag = std::make_unique<StderrStyledUserDiagnostics>(text_formatter);
78 std::filesystem::path project_root = project_root_opt_.
project_root();
79 std::filesystem::path fieldmap_header_root_relative{
"include/fieldmap.h"};
80 std::filesystem::path behaviors_header_root_relative{
"include/constants/metatile_behaviors.h"};
81 std::filesystem::path global_fieldmap_header_root_relative{
"include/global.fieldmap.h"};
84 std::vector<std::unique_ptr<ConfigProvider>> providers{};
85 providers.push_back(std::make_unique<CliOptionProvider>(cli_storage_));
86 auto yaml_provider = std::make_unique<YamlFileProvider>(text_formatter, stderr_diag.get(), project_root);
87 auto *yaml_provider_ptr = yaml_provider.get();
88 providers.push_back(std::move(yaml_provider));
90 std::make_unique<HeaderDefineProvider>(project_root, fieldmap_header_root_relative, text_formatter));
91 providers.push_back(std::make_unique<MetatilesHeaderProvider>(project_root, text_formatter));
92 providers.push_back(std::make_unique<DefaultProvider>());
96 if (yaml_provider_ptr->preload_and_validate(ConfigScopeType::tileset, tileset_name_)) {
98 "Configuration validation failed for tileset '{}'.",
FormatParam{tileset_name_, Style::bold}}};
99 stderr_diag->fatal(validation_err);
100 throw CLI::RuntimeError{1};
104 auto attr_size_check = config.metatile_attr_size(ConfigScopeType::tileset, tileset_name_);
105 if (!attr_size_check.has_value()) {
106 stderr_diag->fatal(attr_size_check);
107 throw CLI::RuntimeError{1};
109 const std::size_t metatile_attr_size = attr_size_check.value().value();
112 auto get_filter_patterns =
114 if (result.has_value()) {
115 return std::move(result).value().value();
117 stderr_diag->fatal(result);
123 get_filter_patterns(config.diagnostic_warnings_exclude(ConfigScopeType::tileset, tileset_name_)),
124 get_filter_patterns(config.diagnostic_warnings_include(ConfigScopeType::tileset, tileset_name_))};
127 get_filter_patterns(config.diagnostic_remarks_exclude(ConfigScopeType::tileset, tileset_name_)),
128 get_filter_patterns(config.diagnostic_remarks_include(ConfigScopeType::tileset, tileset_name_))};
131 auto diag = std::make_unique<FilteredUserDiagnostics>(
132 text_formatter, stderr_diag.get(), std::move(warning_filter), std::move(remark_filter));
134 std::unique_ptr<TilePrinter> tile_printer = std::make_unique<AsciiTilePrinter>(text_formatter);
135 std::unique_ptr<PalettePrinter> pal_printer = std::make_unique<ColorPalettePrinter>(text_formatter);
150 TilesetCompiler compiler{&config, text_formatter, diag.get(), tile_printer.get(), pal_printer.get()};
154 project_root / behaviors_header_root_relative, text_formatter, diag.get()};
168 &tileset_anims_modifier};
171 BaseGameDetector base_game_detector{project_root, text_formatter, diag.get()};
172 auto base_game_result = base_game_detector.
detect();
173 if (!base_game_result.has_value()) {
174 diag->fatal(base_game_result);
175 throw CLI::RuntimeError{1};
177 const BaseGame base_game = base_game_result.value();
180 std::unique_ptr<HeaderTerrainTypeMapProvider> terrain_provider;
181 std::unique_ptr<HeaderEncounterTypeMapProvider> encounter_provider;
182 if (base_game == BaseGame::pokefirered) {
183 terrain_provider = std::make_unique<HeaderTerrainTypeMapProvider>(
184 project_root / global_fieldmap_header_root_relative, text_formatter, diag.get());
185 encounter_provider = std::make_unique<HeaderEncounterTypeMapProvider>(
186 project_root / global_fieldmap_header_root_relative, text_formatter, diag.get());
191 text_formatter, &behavior_map_provider, base_game, terrain_provider.get(), encounter_provider.get()};
195 project_root, &config, &metadata_provider, text_formatter, diag.get()};
202 &attributes_csv_loader,
218 &anim_code_generator,
219 &behavior_map_provider,
220 terrain_provider.get(),
221 encounter_provider.get()};
224 &checksum_provider, &metadata_provider, &key_provider, &artifact_reader, &artifact_writer, diag.get()};
227 &repo, &decompiler, &compiler, &metadata_provider, &tileset_manager, &config, &config, diag.get()};
230 auto decompile_result = decompile_use_case.
decompile(tileset_name_);
231 if (!decompile_result.has_value()) {
235 diag->fatal(fail_result);
236 throw CLI::RuntimeError{1};
241 static constexpr auto kCommandName =
"decompile-tileset";
242 static constexpr auto kCommandDesc =
243 "Decompile a tileset -- update the Porytiles assets to match the Porymap assets.";
244 static constexpr auto kCommandGroup =
"COMMANDS";
245 std::string tileset_name_;
Command is an abstract class that provides basic command functionality for the Porytiles CLI driver.
CLI::App & get_app() const
DecompileTilesetCommand(CLI::App &parent_app)
std::filesystem::path project_root() const
void RegisterOpt(CLI::App &app) override
Generates C header code for tileset animations.
Parses C code to extract tileset animation parameters using callback chain discovery.
Parses and writes animation configuration JSON files (anim.json).
A service that loads metatile attributes from a CSV file.
Detects the base game of a decompilation project.
ChainableResult< BaseGame > detect() const
Detects the base game for the project.
A result type that maintains a chainable sequence of errors for debugging and error reporting.
Use case for decompiling a primary Tileset.
ChainableResult< void > decompile(const std::string &tileset_name) const
Decompiles the primary Tileset with the given tileset name.
Regex-based include/exclude filter for diagnostic tags.
Appends INCBIN declarations for Porytiles-managed tileset assets.
An implementation of FilePalLoader that loads palettes from JASC-PAL (Paintshop Pro) pal files.
An implementation of FilePalSaver that saves palettes to JASC-PAL (Paintshop Pro) pal files.
A Config implementation that lazily pulls a config value by consulting multiple priority-ordered back...
An image loader that reads PNG files to create an Image with an index pixel type.
An image saver that saves PNG files from an Image with an index pixel type.
An image loader that reads PNG files to create an Image with an Rgba32 pixel type.
An image saver that saves PNG files from an Image with an Rgba32 pixel type.
Pokeemerald project filesystem-based implementation of ArtifactChecksumProvider.
Manages Porytiles-owned tilesets via TilesetManifest JSON files.
Modifies tileset_anims.c to include Porytiles-managed animation code headers.
Provides a pokeemerald project filesystem-based implementation for TilesetArtifactKeyProvider.
Provides a filesystem-based implementation for TilesetArtifactReader.
Provides a filesystem-based implementation for TilesetArtifactWriter.
Abstract base class for applying text styling with context-aware formatting.
Service that compiles a Tileset (primary or secondary).
Repository interface for the Tileset aggregate root.
BaseGame
Identifies the target base game for a decompilation project.
void register_config_options(CLI::App &app, CliOptionStorage &storage)
Registers all config options with a CLI11 App.
Storage struct for CLI option values.