123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305 |
- #include <cstddef>
- #include <map>
- #include <memory>
- #include <string>
- #include <vector>
- #include "Common/ColorUtil.h"
- #include "Common/CommonTypes.h"
- #include "Common/StringUtil.h"
- #include "Common/Logging/Log.h"
- #include "DiscIO/Blob.h"
- #include "DiscIO/FileMonitor.h"
- #include "DiscIO/Filesystem.h"
- #include "DiscIO/Volume.h"
- #include "DiscIO/VolumeGC.h"
- namespace DiscIO
- {
- CVolumeGC::CVolumeGC(IBlobReader* _pReader)
- : m_pReader(_pReader)
- {}
- CVolumeGC::~CVolumeGC()
- {
- }
- bool CVolumeGC::Read(u64 _Offset, u64 _Length, u8* _pBuffer, bool decrypt) const
- {
- if (decrypt)
- PanicAlertT("Tried to decrypt data from a non-Wii volume");
- if (m_pReader == nullptr)
- return false;
- FileMon::FindFilename(_Offset);
- return m_pReader->Read(_Offset, _Length, _pBuffer);
- }
- std::string CVolumeGC::GetUniqueID() const
- {
- static const std::string NO_UID("NO_UID");
- if (m_pReader == nullptr)
- return NO_UID;
- char ID[7];
- if (!Read(0, sizeof(ID), reinterpret_cast<u8*>(ID)))
- {
- PanicAlertT("Failed to read unique ID from disc image");
- return NO_UID;
- }
- ID[6] = '\0';
- return ID;
- }
- IVolume::ECountry CVolumeGC::GetCountry() const
- {
- if (!m_pReader)
- return COUNTRY_UNKNOWN;
- u8 country_code;
- m_pReader->Read(3, 1, &country_code);
- return CountrySwitch(country_code);
- }
- std::string CVolumeGC::GetMakerID() const
- {
- if (m_pReader == nullptr)
- return std::string();
- char makerID[3];
- if (!Read(0x4, 0x2, (u8*)&makerID))
- return std::string();
- makerID[2] = '\0';
- return makerID;
- }
- u16 CVolumeGC::GetRevision() const
- {
- if (!m_pReader)
- return 0;
- u8 revision;
- if (!Read(7, 1, &revision))
- return 0;
- return revision;
- }
- std::string CVolumeGC::GetInternalName() const
- {
- char name[0x60];
- if (m_pReader != nullptr && Read(0x20, 0x60, (u8*)name))
- return DecodeString(name);
- else
- return "";
- }
- std::map<IVolume::ELanguage, std::string> CVolumeGC::GetNames(bool prefer_long) const
- {
- return ReadMultiLanguageStrings(false, prefer_long);
- }
- std::map<IVolume::ELanguage, std::string> CVolumeGC::GetDescriptions() const
- {
- return ReadMultiLanguageStrings(true);
- }
- std::string CVolumeGC::GetCompany() const
- {
- if (!LoadBannerFile())
- return "";
- auto const pBanner = (GCBanner*)m_banner_file.data();
- std::string company = DecodeString(pBanner->comment[0].longMaker);
- if (company.empty())
- company = DecodeString(pBanner->comment[0].shortMaker);
- return company;
- }
- std::vector<u32> CVolumeGC::GetBanner(int* width, int* height) const
- {
- if (!LoadBannerFile())
- {
- *width = 0;
- *height = 0;
- return std::vector<u32>();
- }
- std::vector<u32> image_buffer(GC_BANNER_WIDTH * GC_BANNER_HEIGHT);
- auto const pBanner = (GCBanner*)m_banner_file.data();
- ColorUtil::decode5A3image(image_buffer.data(), pBanner->image, GC_BANNER_WIDTH, GC_BANNER_HEIGHT);
- *width = GC_BANNER_WIDTH;
- *height = GC_BANNER_HEIGHT;
- return image_buffer;
- }
- u64 CVolumeGC::GetFSTSize() const
- {
- if (m_pReader == nullptr)
- return 0;
- u32 size;
- if (!Read(0x428, 0x4, (u8*)&size))
- return 0;
- return Common::swap32(size);
- }
- std::string CVolumeGC::GetApploaderDate() const
- {
- if (m_pReader == nullptr)
- return std::string();
- char date[16];
- if (!Read(0x2440, 0x10, (u8*)&date))
- return std::string();
-
- date[10] = '\0';
- return date;
- }
- u64 CVolumeGC::GetSize() const
- {
- if (m_pReader)
- return m_pReader->GetDataSize();
- else
- return 0;
- }
- u64 CVolumeGC::GetRawSize() const
- {
- if (m_pReader)
- return m_pReader->GetRawSize();
- else
- return 0;
- }
- u8 CVolumeGC::GetDiscNumber() const
- {
- u8 disc_number;
- Read(6, 1, &disc_number);
- return disc_number;
- }
- IVolume::EPlatform CVolumeGC::GetVolumeType() const
- {
- return GAMECUBE_DISC;
- }
- bool CVolumeGC::LoadBannerFile() const
- {
-
-
-
-
-
-
- if (m_banner_file_type != BANNER_NOT_LOADED)
- return m_banner_file_type != BANNER_INVALID;
- std::unique_ptr<IFileSystem> file_system(CreateFileSystem(this));
- size_t file_size = (size_t)file_system->GetFileSize("opening.bnr");
- if (file_size == BNR1_SIZE || file_size == BNR2_SIZE)
- {
- m_banner_file.resize(file_size);
- file_system->ReadFile("opening.bnr", m_banner_file.data(), m_banner_file.size());
- u32 bannerSignature = *(u32*)m_banner_file.data();
- if (file_size == BNR1_SIZE && bannerSignature == 0x31524e42)
- {
- m_banner_file_type = BANNER_BNR1;
- }
- else if (file_size == BNR2_SIZE && bannerSignature == 0x32524e42)
- {
- m_banner_file_type = BANNER_BNR2;
- }
- else
- {
- m_banner_file_type = BANNER_INVALID;
- WARN_LOG(DISCIO, "Invalid opening.bnr. Type: %0x Size: %0lx", bannerSignature, (unsigned long)file_size);
- }
- }
- else
- {
- m_banner_file_type = BANNER_INVALID;
- WARN_LOG(DISCIO, "Invalid opening.bnr. Size: %0lx", (unsigned long)file_size);
- }
- return m_banner_file_type != BANNER_INVALID;
- }
- std::map<IVolume::ELanguage, std::string> CVolumeGC::ReadMultiLanguageStrings(bool description, bool prefer_long) const
- {
- std::map<ELanguage, std::string> strings;
- if (!LoadBannerFile())
- return strings;
- u32 number_of_languages = 0;
- ELanguage start_language;
- bool is_japanese = GetCountry() == ECountry::COUNTRY_JAPAN;
- switch (m_banner_file_type)
- {
- case BANNER_BNR1:
- number_of_languages = 1;
- start_language = is_japanese ? ELanguage::LANGUAGE_JAPANESE : ELanguage::LANGUAGE_ENGLISH;
- break;
- case BANNER_BNR2:
- number_of_languages = 6;
- start_language = ELanguage::LANGUAGE_ENGLISH;
- break;
-
- case BANNER_INVALID:
- case BANNER_NOT_LOADED:
- break;
- }
- auto const banner = reinterpret_cast<const GCBanner*>(m_banner_file.data());
- for (u32 i = 0; i < number_of_languages; ++i)
- {
- GCBannerComment comment = banner->comment[i];
- std::string string;
- if (description)
- {
- string = DecodeString(comment.comment);
- }
- else
- {
- if (prefer_long)
- string = DecodeString(comment.longTitle);
- if (string.empty())
- string = DecodeString(comment.shortTitle);
- }
- if (!string.empty())
- strings[(ELanguage)(start_language + i)] = string;
- }
- return strings;
- }
- }
|