diff --git a/Source/Core/DiscIO/Enums.cpp b/Source/Core/DiscIO/Enums.cpp
index 393f30076f..2d6f22d164 100644
--- a/Source/Core/DiscIO/Enums.cpp
+++ b/Source/Core/DiscIO/Enums.cpp
@@ -111,6 +111,32 @@ std::string GetName(Language language, bool translate)
return translate ? Common::GetStringT(name.c_str()) : name;
}
+std::string GetName(Region region, bool translate)
+{
+ std::string name;
+
+ switch (region)
+ {
+ case DiscIO::Region::NTSC_J:
+ name = _trans("NTSC-J");
+ break;
+ case DiscIO::Region::NTSC_U:
+ name = _trans("NTSC-U");
+ break;
+ case DiscIO::Region::PAL:
+ name = _trans("PAL");
+ break;
+ case DiscIO::Region::NTSC_K:
+ name = _trans("NTSC-K");
+ break;
+ default:
+ name = _trans("Unknown");
+ break;
+ }
+
+ return translate ? Common::GetStringT(name.c_str()) : name;
+}
+
bool IsDisc(Platform volume_type)
{
return volume_type == Platform::GameCubeDisc || volume_type == Platform::WiiDisc;
diff --git a/Source/Core/DiscIO/Enums.h b/Source/Core/DiscIO/Enums.h
index ebbef8cd42..4881a8d980 100644
--- a/Source/Core/DiscIO/Enums.h
+++ b/Source/Core/DiscIO/Enums.h
@@ -70,6 +70,7 @@ enum class Language
std::string GetName(Country country, bool translate);
std::string GetName(Language language, bool translate);
+std::string GetName(Region region, bool translate);
bool IsDisc(Platform volume_type);
bool IsWii(Platform volume_type);
diff --git a/Source/Core/DolphinTool/DolphinTool.vcxproj b/Source/Core/DolphinTool/DolphinTool.vcxproj
index eb6b34f30b..9fcfd32020 100644
--- a/Source/Core/DolphinTool/DolphinTool.vcxproj
+++ b/Source/Core/DolphinTool/DolphinTool.vcxproj
@@ -39,6 +39,7 @@
+
diff --git a/Source/Core/DolphinTool/HeaderCommand.cpp b/Source/Core/DolphinTool/HeaderCommand.cpp
index cebb202ce6..7ea194c686 100644
--- a/Source/Core/DolphinTool/HeaderCommand.cpp
+++ b/Source/Core/DolphinTool/HeaderCommand.cpp
@@ -11,6 +11,7 @@
#include
#include
#include
+#include
#include "DiscIO/Blob.h"
#include "DiscIO/Volume.h"
@@ -30,6 +31,10 @@ int HeaderCommand(const std::vector& args)
.help("Path to disc image FILE.")
.metavar("FILE");
+ parser.add_option("-j", "--json")
+ .action("store_true")
+ .help("Optional. Print the information as JSON, then exit. Overrides other print options.");
+
parser.add_option("-b", "--block_size")
.action("store_true")
.help("Optional. Print the block size of GCZ/WIA/RVZ formats, then exit.");
@@ -52,19 +57,58 @@ int HeaderCommand(const std::vector& args)
return EXIT_FAILURE;
}
+ const bool enable_json = options.is_set_by_user("json");
const bool enable_block_size = options.is_set_by_user("block_size");
const bool enable_compression_method = options.is_set_by_user("compression");
const bool enable_compression_level = options.is_set_by_user("compression_level");
- // Open the blob reader, plus get blob type
+ // Open the blob reader
const std::unique_ptr blob_reader = DiscIO::CreateBlobReader(input_file_path);
if (!blob_reader)
{
fmt::print(std::cerr, "Error: Unable to open disc image\n");
return EXIT_FAILURE;
}
+ // Open the volume
+ const std::unique_ptr volume = DiscIO::CreateVolume(blob_reader->CopyReader());
- if (enable_block_size || enable_compression_method || enable_compression_level)
+ if (enable_json)
+ {
+ auto json = picojson::object();
+
+ // File data
+ if (const u64 block_size = blob_reader->GetBlockSize())
+ json["block_size"] = picojson::value((double)block_size);
+
+ const std::string compression_method = blob_reader->GetCompressionMethod();
+ if (compression_method != "")
+ json["compression_method"] = picojson::value(compression_method);
+
+ if (const std::optional compression_level = blob_reader->GetCompressionLevel())
+ json["compression_level"] = picojson::value((double)compression_level.value());
+
+ // Game data
+ if (volume)
+ {
+ json["internal_name"] = picojson::value(volume->GetInternalName());
+
+ if (const std::optional revision = volume->GetRevision())
+ json["revision"] = picojson::value((double)revision.value());
+
+ json["game_id"] = picojson::value(volume->GetGameID());
+
+ if (const std::optional title_id = volume->GetTitleID())
+ json["title_id"] = picojson::value((double)title_id.value());
+
+ json["region"] = picojson::value(DiscIO::GetName(volume->GetRegion(), false));
+
+ json["country"] = picojson::value(DiscIO::GetName(volume->GetCountry(), false));
+ }
+
+ // Print
+ std::cout << picojson::value(json) << '\n';
+ }
+ else if (enable_block_size || enable_compression_method || enable_compression_level)
{
if (enable_block_size)
{
@@ -93,17 +137,33 @@ int HeaderCommand(const std::vector& args)
}
else
{
- const auto blob_type = blob_reader->GetBlobType();
- if (blob_type == DiscIO::BlobType::GCZ)
+ // File data
+ if (const u64 block_size = blob_reader->GetBlockSize())
+ fmt::print(std::cout, "Block Size: {}\n", block_size);
+
+ const std::string compression_method = blob_reader->GetCompressionMethod();
+ if (compression_method != "")
+ fmt::print(std::cout, "Compression Method: {}\n", compression_method);
+
+ if (const std::optional compression_level = blob_reader->GetCompressionLevel())
+ fmt::print(std::cout, "Compression Level: {}\n", compression_level.value());
+
+ // Game data
+ if (volume)
{
- fmt::print(std::cout, "Block Size: {}\nCompression Method: {}\n", blob_reader->GetBlockSize(),
- blob_reader->GetCompressionMethod());
- }
- if (blob_type == DiscIO::BlobType::WIA || blob_type == DiscIO::BlobType::RVZ)
- {
- fmt::print(std::cout, "Block Size: {}\nCompression Method: {}\nCompression Level: {}\n",
- blob_reader->GetBlockSize(), blob_reader->GetCompressionMethod(),
- blob_reader->GetCompressionLevel().value());
+ fmt::print(std::cout, "Internal Name: {}\n", volume->GetInternalName());
+
+ if (const std::optional revision = volume->GetRevision())
+ fmt::print(std::cout, "Revision: {}\n", revision.value());
+
+ fmt::print(std::cout, "Game ID: {}\n", volume->GetGameID());
+
+ if (const std::optional title_id = volume->GetTitleID())
+ fmt::print(std::cout, "Title ID: {}\n", title_id.value());
+
+ fmt::print(std::cout, "Region: {}\n", DiscIO::GetName(volume->GetRegion(), false));
+
+ fmt::print(std::cout, "Country: {}\n", DiscIO::GetName(volume->GetCountry(), false));
}
}