DiscIO: Use Common::Lazy for loading GC banners

This commit is contained in:
JosJuice 2017-08-02 19:06:32 +02:00
parent ca36c977d9
commit f294599e73
3 changed files with 51 additions and 60 deletions

View File

@ -36,6 +36,8 @@ VolumeGC::VolumeGC(std::unique_ptr<BlobReader> reader) : m_pReader(std::move(rea
auto file_system = std::make_unique<FileSystemGCWii>(this, PARTITION_NONE); auto file_system = std::make_unique<FileSystemGCWii>(this, PARTITION_NONE);
return file_system->IsValid() ? std::move(file_system) : nullptr; return file_system->IsValid() ? std::move(file_system) : nullptr;
}; };
m_converted_banner = [this] { return LoadBannerFile(); };
} }
VolumeGC::~VolumeGC() VolumeGC::~VolumeGC()
@ -125,40 +127,34 @@ std::string VolumeGC::GetInternalName(const Partition& partition) const
std::map<Language, std::string> VolumeGC::GetShortNames() const std::map<Language, std::string> VolumeGC::GetShortNames() const
{ {
LoadBannerFile(); return m_converted_banner->short_names;
return m_short_names;
} }
std::map<Language, std::string> VolumeGC::GetLongNames() const std::map<Language, std::string> VolumeGC::GetLongNames() const
{ {
LoadBannerFile(); return m_converted_banner->long_names;
return m_long_names;
} }
std::map<Language, std::string> VolumeGC::GetShortMakers() const std::map<Language, std::string> VolumeGC::GetShortMakers() const
{ {
LoadBannerFile(); return m_converted_banner->short_makers;
return m_short_makers;
} }
std::map<Language, std::string> VolumeGC::GetLongMakers() const std::map<Language, std::string> VolumeGC::GetLongMakers() const
{ {
LoadBannerFile(); return m_converted_banner->long_makers;
return m_long_makers;
} }
std::map<Language, std::string> VolumeGC::GetDescriptions() const std::map<Language, std::string> VolumeGC::GetDescriptions() const
{ {
LoadBannerFile(); return m_converted_banner->descriptions;
return m_descriptions;
} }
std::vector<u32> VolumeGC::GetBanner(int* width, int* height) const std::vector<u32> VolumeGC::GetBanner(int* width, int* height) const
{ {
LoadBannerFile(); *width = m_converted_banner->image_width;
*width = m_image_width; *height = m_converted_banner->image_height;
*height = m_image_height; return m_converted_banner->image_buffer;
return m_image_buffer;
} }
std::string VolumeGC::GetApploaderDate(const Partition& partition) const std::string VolumeGC::GetApploaderDate(const Partition& partition) const
@ -195,21 +191,15 @@ Platform VolumeGC::GetVolumeType() const
return Platform::GAMECUBE_DISC; return Platform::GAMECUBE_DISC;
} }
void VolumeGC::LoadBannerFile() const VolumeGC::ConvertedGCBanner VolumeGC::LoadBannerFile() const
{ {
// If opening.bnr has been loaded already, return immediately
if (m_banner_loaded)
return;
m_banner_loaded = true;
GCBanner banner_file; GCBanner banner_file;
const u64 file_size = ReadFile(*this, PARTITION_NONE, "opening.bnr", const u64 file_size = ReadFile(*this, PARTITION_NONE, "opening.bnr",
reinterpret_cast<u8*>(&banner_file), sizeof(GCBanner)); reinterpret_cast<u8*>(&banner_file), sizeof(GCBanner));
if (file_size < 4) if (file_size < 4)
{ {
WARN_LOG(DISCIO, "Could not read opening.bnr."); WARN_LOG(DISCIO, "Could not read opening.bnr.");
return; // Return early so that we don't access the uninitialized banner_file.id return {}; // Return early so that we don't access the uninitialized banner_file.id
} }
constexpr u32 BNR1_MAGIC = 0x31524e42; constexpr u32 BNR1_MAGIC = 0x31524e42;
@ -226,14 +216,17 @@ void VolumeGC::LoadBannerFile() const
else else
{ {
WARN_LOG(DISCIO, "Invalid opening.bnr. Type: %0x Size: %0zx", banner_file.id, file_size); WARN_LOG(DISCIO, "Invalid opening.bnr. Type: %0x Size: %0zx", banner_file.id, file_size);
return; return {};
} }
ExtractBannerInformation(banner_file, is_bnr1); return ExtractBannerInformation(banner_file, is_bnr1);
} }
void VolumeGC::ExtractBannerInformation(const GCBanner& banner_file, bool is_bnr1) const VolumeGC::ConvertedGCBanner VolumeGC::ExtractBannerInformation(const GCBanner& banner_file,
bool is_bnr1) const
{ {
ConvertedGCBanner banner;
u32 number_of_languages = 0; u32 number_of_languages = 0;
Language start_language = Language::LANGUAGE_UNKNOWN; Language start_language = Language::LANGUAGE_UNKNOWN;
@ -249,11 +242,11 @@ void VolumeGC::ExtractBannerInformation(const GCBanner& banner_file, bool is_bnr
start_language = Language::LANGUAGE_ENGLISH; start_language = Language::LANGUAGE_ENGLISH;
} }
m_image_width = GC_BANNER_WIDTH; banner.image_width = GC_BANNER_WIDTH;
m_image_height = GC_BANNER_HEIGHT; banner.image_height = GC_BANNER_HEIGHT;
m_image_buffer = std::vector<u32>(m_image_width * m_image_height); banner.image_buffer = std::vector<u32>(GC_BANNER_WIDTH * GC_BANNER_HEIGHT);
ColorUtil::decode5A3image(m_image_buffer.data(), banner_file.image, m_image_width, ColorUtil::decode5A3image(banner.image_buffer.data(), banner_file.image, GC_BANNER_WIDTH,
m_image_height); GC_BANNER_HEIGHT);
for (u32 i = 0; i < number_of_languages; ++i) for (u32 i = 0; i < number_of_languages; ++i)
{ {
@ -262,24 +255,26 @@ void VolumeGC::ExtractBannerInformation(const GCBanner& banner_file, bool is_bnr
std::string description = DecodeString(info.description); std::string description = DecodeString(info.description);
if (!description.empty()) if (!description.empty())
m_descriptions[language] = description; banner.descriptions.emplace(language, description);
std::string short_name = DecodeString(info.short_name); std::string short_name = DecodeString(info.short_name);
if (!short_name.empty()) if (!short_name.empty())
m_short_names[language] = short_name; banner.short_names.emplace(language, short_name);
std::string long_name = DecodeString(info.long_name); std::string long_name = DecodeString(info.long_name);
if (!long_name.empty()) if (!long_name.empty())
m_long_names[language] = long_name; banner.long_names.emplace(language, long_name);
std::string short_maker = DecodeString(info.short_maker); std::string short_maker = DecodeString(info.short_maker);
if (!short_maker.empty()) if (!short_maker.empty())
m_short_makers[language] = short_maker; banner.short_makers.emplace(language, short_maker);
std::string long_maker = DecodeString(info.long_maker); std::string long_maker = DecodeString(info.long_maker);
if (!long_maker.empty()) if (!long_maker.empty())
m_long_makers[language] = long_maker; banner.long_makers.emplace(language, long_maker);
} }
return banner;
} }
} // namespace } // namespace

View File

@ -79,23 +79,26 @@ private:
// (only one for BNR1 type) // (only one for BNR1 type)
}; };
void LoadBannerFile() const; struct ConvertedGCBanner
void ExtractBannerInformation(const GCBanner& banner_file, bool is_bnr1) const; {
std::map<Language, std::string> short_names;
std::map<Language, std::string> long_names;
std::map<Language, std::string> short_makers;
std::map<Language, std::string> long_makers;
std::map<Language, std::string> descriptions;
std::vector<u32> image_buffer;
int image_height = 0;
int image_width = 0;
};
ConvertedGCBanner LoadBannerFile() const;
ConvertedGCBanner ExtractBannerInformation(const GCBanner& banner_file, bool is_bnr1) const;
static const size_t BNR1_SIZE = sizeof(GCBanner) - sizeof(GCBannerInformation) * 5; static const size_t BNR1_SIZE = sizeof(GCBanner) - sizeof(GCBannerInformation) * 5;
static const size_t BNR2_SIZE = sizeof(GCBanner); static const size_t BNR2_SIZE = sizeof(GCBanner);
mutable std::map<Language, std::string> m_short_names; Common::Lazy<ConvertedGCBanner> m_converted_banner;
mutable std::map<Language, std::string> m_long_names;
mutable std::map<Language, std::string> m_short_makers;
mutable std::map<Language, std::string> m_long_makers;
mutable std::map<Language, std::string> m_descriptions;
mutable bool m_banner_loaded = false;
mutable std::vector<u32> m_image_buffer;
mutable int m_image_height = 0;
mutable int m_image_width = 0;
Common::Lazy<std::unique_ptr<FileSystem>> m_file_system; Common::Lazy<std::unique_ptr<FileSystem>> m_file_system;

View File

@ -85,8 +85,7 @@ void FilesystemWidget::PopulateView()
for (size_t i = 0; i < partitions.size(); i++) for (size_t i = 0; i < partitions.size(); i++)
{ {
std::unique_ptr<DiscIO::FileSystem> file_system( const DiscIO::FileSystem* file_system = m_volume->GetFileSystem(partitions[i]);
DiscIO::CreateFileSystem(m_volume.get(), partitions[i]));
auto* item = new QStandardItem(tr("Partition %1").arg(i)); auto* item = new QStandardItem(tr("Partition %1").arg(i));
item->setEditable(false); item->setEditable(false);
@ -104,10 +103,7 @@ void FilesystemWidget::PopulateView()
} }
if (partitions.empty()) if (partitions.empty())
{ PopulateDirectory(-1, disc, m_volume->GetFileSystem(DiscIO::PARTITION_NONE)->GetRoot());
PopulateDirectory(-1, disc,
DiscIO::CreateFileSystem(m_volume.get(), DiscIO::PARTITION_NONE)->GetRoot());
}
} }
void FilesystemWidget::PopulateDirectory(int partition_id, QStandardItem* root, void FilesystemWidget::PopulateDirectory(int partition_id, QStandardItem* root,
@ -237,9 +233,7 @@ void FilesystemWidget::ExtractSystemData(const DiscIO::Partition& partition, con
void FilesystemWidget::ExtractDirectory(const DiscIO::Partition& partition, const QString path, void FilesystemWidget::ExtractDirectory(const DiscIO::Partition& partition, const QString path,
const QString& out) const QString& out)
{ {
std::unique_ptr<DiscIO::FileSystem> filesystem( const DiscIO::FileSystem* filesystem = m_volume->GetFileSystem(partition);
DiscIO::CreateFileSystem(m_volume.get(), partition));
std::unique_ptr<DiscIO::FileInfo> info = filesystem->FindFileInfo(path.toStdString()); std::unique_ptr<DiscIO::FileInfo> info = filesystem->FindFileInfo(path.toStdString());
u32 size = info->GetTotalChildren(); u32 size = info->GetTotalChildren();
@ -251,7 +245,7 @@ void FilesystemWidget::ExtractDirectory(const DiscIO::Partition& partition, cons
bool all = path.isEmpty(); bool all = path.isEmpty();
DiscIO::ExportDirectory( DiscIO::ExportDirectory(
*m_volume, filesystem->GetPartition(), *info, true, path.toStdString(), out.toStdString(), *m_volume, partition, *info, true, path.toStdString(), out.toStdString(),
[all, dialog](const std::string& current) { [all, dialog](const std::string& current) {
dialog->setLabelText( dialog->setLabelText(
(all ? QObject::tr("Extracting All Files...") : QObject::tr("Extracting Directory...")) (all ? QObject::tr("Extracting All Files...") : QObject::tr("Extracting Directory..."))
@ -268,8 +262,7 @@ void FilesystemWidget::ExtractDirectory(const DiscIO::Partition& partition, cons
void FilesystemWidget::ExtractFile(const DiscIO::Partition& partition, const QString& path, void FilesystemWidget::ExtractFile(const DiscIO::Partition& partition, const QString& path,
const QString& out) const QString& out)
{ {
std::unique_ptr<DiscIO::FileSystem> filesystem( const DiscIO::FileSystem* filesystem = m_volume->GetFileSystem(partition);
DiscIO::CreateFileSystem(m_volume.get(), partition));
bool success = DiscIO::ExportFile( bool success = DiscIO::ExportFile(
*m_volume, partition, filesystem->FindFileInfo(path.toStdString()).get(), out.toStdString()); *m_volume, partition, filesystem->FindFileInfo(path.toStdString()).get(), out.toStdString());