HeaderCommand.cpp 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173
  1. // Copyright 2022 Dolphin Emulator Project
  2. // SPDX-License-Identifier: GPL-2.0-or-later
  3. #include "DolphinTool/HeaderCommand.h"
  4. #include <cstdlib>
  5. #include <optional>
  6. #include <string>
  7. #include <vector>
  8. #include <OptionParser.h>
  9. #include <fmt/format.h>
  10. #include <fmt/ostream.h>
  11. #include <picojson.h>
  12. #include "DiscIO/Blob.h"
  13. #include "DiscIO/Volume.h"
  14. #include "DiscIO/VolumeDisc.h"
  15. namespace DolphinTool
  16. {
  17. int HeaderCommand(const std::vector<std::string>& args)
  18. {
  19. optparse::OptionParser parser;
  20. parser.usage("usage: header [options]...");
  21. parser.add_option("-i", "--input")
  22. .type("string")
  23. .action("store")
  24. .help("Path to disc image FILE.")
  25. .metavar("FILE");
  26. parser.add_option("-j", "--json")
  27. .action("store_true")
  28. .help("Optional. Print the information as JSON, then exit. Overrides other print options.");
  29. parser.add_option("-b", "--block_size")
  30. .action("store_true")
  31. .help("Optional. Print the block size of GCZ/WIA/RVZ formats, then exit.");
  32. parser.add_option("-c", "--compression")
  33. .action("store_true")
  34. .help("Optional. Print the compression method of GCZ/WIA/RVZ formats, then exit.");
  35. parser.add_option("-l", "--compression_level")
  36. .action("store_true")
  37. .help("Optional. Print the level of compression for WIA/RVZ formats, then exit.");
  38. const optparse::Values& options = parser.parse_args(args);
  39. // Validate options
  40. const std::string& input_file_path = options["input"];
  41. if (input_file_path.empty())
  42. {
  43. fmt::print(std::cerr, "Error: No input set\n");
  44. return EXIT_FAILURE;
  45. }
  46. const bool enable_json = options.is_set_by_user("json");
  47. const bool enable_block_size = options.is_set_by_user("block_size");
  48. const bool enable_compression_method = options.is_set_by_user("compression");
  49. const bool enable_compression_level = options.is_set_by_user("compression_level");
  50. // Open the blob reader
  51. const std::unique_ptr<DiscIO::BlobReader> blob_reader = DiscIO::CreateBlobReader(input_file_path);
  52. if (!blob_reader)
  53. {
  54. fmt::print(std::cerr, "Error: Unable to open disc image\n");
  55. return EXIT_FAILURE;
  56. }
  57. // Open the volume
  58. const std::unique_ptr<DiscIO::Volume> volume = DiscIO::CreateVolume(blob_reader->CopyReader());
  59. if (enable_json)
  60. {
  61. auto json = picojson::object();
  62. // File data
  63. if (const u64 block_size = blob_reader->GetBlockSize())
  64. json["block_size"] = picojson::value((double)block_size);
  65. const std::string compression_method = blob_reader->GetCompressionMethod();
  66. if (compression_method != "")
  67. json["compression_method"] = picojson::value(compression_method);
  68. if (const std::optional<int> compression_level = blob_reader->GetCompressionLevel())
  69. json["compression_level"] = picojson::value((double)compression_level.value());
  70. // Game data
  71. if (volume)
  72. {
  73. json["internal_name"] = picojson::value(volume->GetInternalName());
  74. if (const std::optional<u16> revision = volume->GetRevision())
  75. json["revision"] = picojson::value((double)revision.value());
  76. json["game_id"] = picojson::value(volume->GetGameID());
  77. if (const std::optional<u64> title_id = volume->GetTitleID())
  78. json["title_id"] = picojson::value((double)title_id.value());
  79. json["region"] = picojson::value(DiscIO::GetName(volume->GetRegion(), false));
  80. json["country"] = picojson::value(DiscIO::GetName(volume->GetCountry(), false));
  81. }
  82. // Print
  83. std::cout << picojson::value(json) << '\n';
  84. }
  85. else if (enable_block_size || enable_compression_method || enable_compression_level)
  86. {
  87. if (enable_block_size)
  88. {
  89. const auto block_size = blob_reader->GetBlockSize();
  90. if (block_size == 0)
  91. fmt::print(std::cout, "N/A\n");
  92. else
  93. fmt::print(std::cout, "{}\n", block_size);
  94. }
  95. if (enable_compression_method)
  96. {
  97. const auto compression_method = blob_reader->GetCompressionMethod();
  98. if (compression_method == "")
  99. fmt::print(std::cout, "N/A\n");
  100. else
  101. fmt::print(std::cout, "{}\n", compression_method);
  102. }
  103. if (enable_compression_level)
  104. {
  105. const auto compression_level_o = blob_reader->GetCompressionLevel();
  106. if (compression_level_o == std::nullopt)
  107. fmt::print(std::cout, "N/A\n");
  108. else
  109. fmt::print(std::cout, "{}\n", compression_level_o.value());
  110. }
  111. }
  112. else
  113. {
  114. // File data
  115. if (const u64 block_size = blob_reader->GetBlockSize())
  116. fmt::print(std::cout, "Block Size: {}\n", block_size);
  117. const std::string compression_method = blob_reader->GetCompressionMethod();
  118. if (compression_method != "")
  119. fmt::print(std::cout, "Compression Method: {}\n", compression_method);
  120. if (const std::optional<int> compression_level = blob_reader->GetCompressionLevel())
  121. fmt::print(std::cout, "Compression Level: {}\n", compression_level.value());
  122. // Game data
  123. if (volume)
  124. {
  125. fmt::print(std::cout, "Internal Name: {}\n", volume->GetInternalName());
  126. if (const std::optional<u16> revision = volume->GetRevision())
  127. fmt::print(std::cout, "Revision: {}\n", revision.value());
  128. fmt::print(std::cout, "Game ID: {}\n", volume->GetGameID());
  129. if (const std::optional<u64> title_id = volume->GetTitleID())
  130. fmt::print(std::cout, "Title ID: {:016x}\n", title_id.value());
  131. fmt::print(std::cout, "Region: {}\n", DiscIO::GetName(volume->GetRegion(), false));
  132. fmt::print(std::cout, "Country: {}\n", DiscIO::GetName(volume->GetCountry(), false));
  133. }
  134. }
  135. return EXIT_SUCCESS;
  136. }
  137. } // namespace DolphinTool