Merge pull request #2286 from JosJuice/wii-opening-bnr

Read opening.bnr to get names from Wii discs
This commit is contained in:
comex
2015-05-05 16:20:04 -04:00
42 changed files with 728 additions and 1079 deletions

View File

@ -18,7 +18,6 @@
#include "Core/ConfigManager.h"
#include "DiscIO/BannerLoader.h"
#include "DiscIO/CompressedBlob.h"
#include "DiscIO/Filesystem.h"
@ -26,25 +25,50 @@
#include "DolphinQt/Utils/Resources.h"
#include "DolphinQt/Utils/Utils.h"
static const u32 CACHE_REVISION = 0x006;
static const u32 CACHE_REVISION = 0x007;
static const u32 DATASTREAM_REVISION = 15; // Introduced in Qt 5.2
static QStringList VectorToStringList(std::vector<std::string> vec, bool trim = false)
static QMap<IVolume::ELanguage, QString> ConvertLocalizedStrings(std::map<IVolume::ELanguage, std::string> strings)
{
QStringList result;
if (trim)
{
for (const std::string& member : vec)
result.append(QString::fromStdString(member).trimmed());
}
else
{
for (const std::string& member : vec)
result.append(QString::fromStdString(member));
}
QMap<IVolume::ELanguage, QString> result;
for (auto entry : strings)
result.insert(entry.first, QString::fromStdString(entry.second).trimmed());
return result;
}
template<class to, class from>
static QMap<to, QString> CastLocalizedStrings(QMap<from, QString> strings)
{
QMap<to, QString> result;
auto end = strings.cend();
for (auto it = strings.cbegin(); it != end; ++it)
result.insert((to)it.key(), it.value());
return result;
}
static QString GetLanguageString(IVolume::ELanguage language, QMap<IVolume::ELanguage, QString> strings)
{
if (strings.contains(language))
return strings.value(language);
// English tends to be a good fallback when the requested language isn't available
if (language != IVolume::ELanguage::LANGUAGE_ENGLISH)
{
if (strings.contains(IVolume::ELanguage::LANGUAGE_ENGLISH))
return strings.value(IVolume::ELanguage::LANGUAGE_ENGLISH);
}
// If English isn't available either, just pick something
if (!strings.empty())
return strings.cbegin().value();
return SL("");
}
GameFile::GameFile(const QString& fileName)
: m_file_name(fileName)
{
@ -57,7 +81,7 @@ GameFile::GameFile(const QString& fileName)
}
else
{
DiscIO::IVolume* volume = DiscIO::CreateVolumeFromFilename(fileName.toStdString());
std::unique_ptr<DiscIO::IVolume> volume(DiscIO::CreateVolumeFromFilename(fileName.toStdString()));
if (volume != nullptr)
{
@ -66,7 +90,9 @@ GameFile::GameFile(const QString& fileName)
else
m_platform = WII_WAD;
m_volume_names = VectorToStringList(volume->GetNames());
m_names = ConvertLocalizedStrings(volume->GetNames());
m_descriptions = ConvertLocalizedStrings(volume->GetDescriptions());
m_company = QString::fromStdString(volume->GetCompany());
m_country = volume->GetCountry();
m_file_size = volume->GetRawSize();
@ -80,43 +106,22 @@ GameFile::GameFile(const QString& fileName)
QFileInfo info(m_file_name);
m_folder_name = info.absoluteDir().dirName();
// check if we can get some info from the banner file too
DiscIO::IFileSystem* fileSystem = DiscIO::CreateFileSystem(volume);
if (fileSystem != nullptr || m_platform == WII_WAD)
int width, height;
std::vector<u32> buffer = volume->GetBanner(&width, &height);
QImage banner(width, height, QImage::Format_RGB888);
for (int i = 0; i < width * height; i++)
{
std::unique_ptr<DiscIO::IBannerLoader> bannerLoader(DiscIO::CreateBannerLoader(*fileSystem, volume));
if (bannerLoader != nullptr)
{
if (bannerLoader->IsValid())
{
if (m_platform != WII_WAD)
m_names = VectorToStringList(bannerLoader->GetNames());
m_company = QString::fromStdString(bannerLoader->GetCompany());
m_descriptions = VectorToStringList(bannerLoader->GetDescriptions(), true);
int width, height;
std::vector<u32> buffer = bannerLoader->GetBanner(&width, &height);
QImage banner(width, height, QImage::Format_RGB888);
for (int i = 0; i < width * height; i++)
{
int x = i % width, y = i / width;
banner.setPixel(x, y, qRgb((buffer[i] & 0xFF0000) >> 16,
(buffer[i] & 0x00FF00) >> 8,
(buffer[i] & 0x0000FF) >> 0));
}
if (!banner.isNull())
{
hasBanner = true;
m_banner = QPixmap::fromImage(banner);
}
}
}
delete fileSystem;
int x = i % width, y = i / width;
banner.setPixel(x, y, qRgb((buffer[i] & 0xFF0000) >> 16,
(buffer[i] & 0x00FF00) >> 8,
(buffer[i] & 0x0000FF) >> 0));
}
if (!banner.isNull())
{
hasBanner = true;
m_banner = QPixmap::fromImage(banner);
}
delete volume;
m_valid = true;
if (hasBanner)
@ -158,11 +163,13 @@ bool GameFile::LoadFromCache()
if (cache_rev != CACHE_REVISION)
return false;
int country;
u32 country;
QMap<u8, QString> names;
QMap<u8, QString> descriptions;
stream >> m_folder_name
>> m_volume_names
>> names
>> descriptions
>> m_company
>> m_descriptions
>> m_unique_id
>> m_file_size
>> m_volume_size
@ -173,6 +180,8 @@ bool GameFile::LoadFromCache()
>> m_is_disc_two
>> m_revision;
m_country = (DiscIO::IVolume::ECountry)country;
m_names = CastLocalizedStrings<IVolume::ELanguage>(names);
m_descriptions = CastLocalizedStrings<IVolume::ELanguage>(descriptions);
file.close();
return true;
}
@ -198,13 +207,13 @@ void GameFile::SaveToCache()
stream << CACHE_REVISION;
stream << m_folder_name
<< m_volume_names
<< CastLocalizedStrings<u8>(m_names)
<< CastLocalizedStrings<u8>(m_descriptions)
<< m_company
<< m_descriptions
<< m_unique_id
<< m_file_size
<< m_volume_size
<< (int)m_country
<< (u32)m_country
<< m_banner
<< m_compressed
<< m_platform
@ -233,56 +242,27 @@ QString GameFile::CreateCacheFilename()
QString GameFile::GetCompany() const
{
if (m_company.isEmpty())
return QObject::tr("N/A");
else
return m_company;
return m_company;
}
// For all of the following functions that accept an "index" parameter,
// (-1 = Japanese, 0 = English, etc)?
QString GameFile::GetDescription(int index) const
QString GameFile::GetDescription(IVolume::ELanguage language) const
{
if (index < m_descriptions.size())
return m_descriptions[index];
if (!m_descriptions.empty())
return m_descriptions[0];
return SL("");
return GetLanguageString(language, m_descriptions);
}
QString GameFile::GetVolumeName(int index) const
QString GameFile::GetDescription() const
{
if (index < m_volume_names.size() && !m_volume_names[index].isEmpty())
return m_volume_names[index];
if (!m_volume_names.isEmpty())
return m_volume_names[0];
return SL("");
return GetDescription(SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(m_platform != GAMECUBE_DISC));
}
QString GameFile::GetBannerName(int index) const
QString GameFile::GetName(IVolume::ELanguage language) const
{
if (index < m_names.size() && !m_names[index].isEmpty())
return m_names[index];
if (!m_names.isEmpty())
return m_names[0];
return SL("");
return GetLanguageString(language, m_names);
}
QString GameFile::GetName(int index) const
QString GameFile::GetName() const
{
// Prefer name from banner, fallback to name from volume, fallback to filename
QString name = GetBannerName(index);
if (name.isEmpty())
name = GetVolumeName(index);
QString name = GetName(SConfig::GetInstance().m_LocalCoreStartupParameter.GetCurrentLanguage(m_platform != GAMECUBE_DISC));
if (name.isEmpty())
{
// No usable name, return filename (better than nothing)
@ -290,7 +270,6 @@ QString GameFile::GetName(int index) const
SplitPath(m_file_name.toStdString(), nullptr, &nametemp, nullptr);
name = QString::fromStdString(nametemp);
}
return name;
}

View File

@ -4,9 +4,9 @@
#pragma once
#include <QMap>
#include <QPixmap>
#include <QString>
#include <QStringList>
#include <string>
@ -22,11 +22,11 @@ public:
bool IsValid() const { return m_valid; }
QString GetFileName() { return m_file_name; }
QString GetFolderName() { return m_folder_name; }
QString GetBannerName(int index) const;
QString GetVolumeName(int index) const;
QString GetName(int index) const;
QString GetName(DiscIO::IVolume::ELanguage language) const;
QString GetName() const;
QString GetDescription(DiscIO::IVolume::ELanguage language) const;
QString GetDescription() const;
QString GetCompany() const;
QString GetDescription(int index = 0) const;
int GetRevision() const { return m_revision; }
const QString GetUniqueID() const { return m_unique_id; }
const QString GetWiiFSPath() const;
@ -52,12 +52,9 @@ private:
QString m_file_name;
QString m_folder_name;
// TODO: eliminate this and overwrite with names from banner when available?
QStringList m_volume_names;
QMap<DiscIO::IVolume::ELanguage, QString> m_names;
QMap<DiscIO::IVolume::ELanguage, QString> m_descriptions;
QString m_company;
QStringList m_names;
QStringList m_descriptions;
QString m_unique_id;

View File

@ -76,7 +76,7 @@ void DGameGrid::AddGame(GameFile* gameItem)
QListWidgetItem* i = new QListWidgetItem;
i->setIcon(QIcon(gameItem->GetBitmap()
.scaled(GRID_BANNER_WIDTH, GRID_BANNER_HEIGHT, Qt::KeepAspectRatio, Qt::SmoothTransformation)));
i->setText(gameItem->GetName(0));
i->setText(gameItem->GetName());
if (gameItem->IsCompressed())
i->setTextColor(QColor("#00F"));

View File

@ -110,7 +110,7 @@ void DGameTree::AddGame(GameFile* item)
QTreeWidgetItem* i = new QTreeWidgetItem;
i->setIcon(COL_TYPE, QIcon(Resources::GetPlatformPixmap(item->GetPlatform())));
i->setIcon(COL_BANNER, QIcon(item->GetBitmap()));
i->setText(COL_TITLE, item->GetName(0));
i->setText(COL_TITLE, item->GetName());
i->setText(COL_DESCRIPTION, item->GetDescription());
i->setIcon(COL_REGION, QIcon(Resources::GetRegionPixmap(item->GetCountry())));
i->setText(COL_SIZE, NiceSizeFormat(item->GetFileSize()));