mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 06:09:50 -06:00
Get rid of banner loaders and move their functionality to volumes
Having some data available in banner loaders and some other data data available in volumes gets messy, especially with GetNames(), which is available in both but returns different results depending on which one is used. This change drops support for reading names and descriptions from Wii save data.
This commit is contained in:
@ -1,28 +0,0 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cstddef>
|
||||
|
||||
#include "DiscIO/BannerLoader.h"
|
||||
#include "DiscIO/BannerLoaderGC.h"
|
||||
#include "DiscIO/BannerLoaderWii.h"
|
||||
#include "DiscIO/Filesystem.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
|
||||
class IBannerLoader;
|
||||
class IVolume;
|
||||
|
||||
IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume *pVolume)
|
||||
{
|
||||
if (pVolume->IsWiiDisc() || pVolume->IsWadFile())
|
||||
return new CBannerLoaderWii(pVolume);
|
||||
if (_rFileSystem.IsValid())
|
||||
return new CBannerLoaderGC(_rFileSystem, pVolume);
|
||||
|
||||
return nullptr;
|
||||
}
|
||||
|
||||
} // namespace
|
@ -1,49 +0,0 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
|
||||
class IFileSystem;
|
||||
class IVolume;
|
||||
|
||||
class IBannerLoader
|
||||
{
|
||||
public:
|
||||
IBannerLoader()
|
||||
: m_IsValid(false)
|
||||
, m_pBannerFile(nullptr)
|
||||
{}
|
||||
|
||||
virtual ~IBannerLoader()
|
||||
{}
|
||||
|
||||
virtual std::vector<u32> GetBanner(int* pWidth, int* pHeight) = 0;
|
||||
|
||||
virtual std::map<IVolume::ELanguage, std::string> GetNames() = 0;
|
||||
virtual std::string GetCompany() = 0;
|
||||
virtual std::map<IVolume::ELanguage, std::string> GetDescriptions() = 0;
|
||||
|
||||
bool IsValid()
|
||||
{
|
||||
return m_IsValid;
|
||||
}
|
||||
|
||||
protected:
|
||||
bool m_IsValid;
|
||||
u8* m_pBannerFile;
|
||||
};
|
||||
|
||||
IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume *pVolume);
|
||||
|
||||
} // namespace DiscIO
|
@ -1,187 +0,0 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <cstddef>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/ColorUtil.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/MsgHandler.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "DiscIO/BannerLoaderGC.h"
|
||||
#include "DiscIO/Filesystem.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
CBannerLoaderGC::CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume* volume)
|
||||
: m_country(volume->GetCountry())
|
||||
{
|
||||
// load the opening.bnr
|
||||
size_t FileSize = (size_t) _rFileSystem.GetFileSize("opening.bnr");
|
||||
if (FileSize == BNR1_SIZE || FileSize == BNR2_SIZE)
|
||||
{
|
||||
m_pBannerFile = new u8[FileSize];
|
||||
if (m_pBannerFile)
|
||||
{
|
||||
_rFileSystem.ReadFile("opening.bnr", m_pBannerFile, FileSize);
|
||||
m_BNRType = getBannerType();
|
||||
if (m_BNRType == BANNER_UNKNOWN)
|
||||
PanicAlertT("Invalid opening.bnr found in gcm:\n%s\n You may need to redump this game.",
|
||||
_rFileSystem.GetVolume()->GetName().c_str());
|
||||
else m_IsValid = true;
|
||||
}
|
||||
}
|
||||
else WARN_LOG(DISCIO, "Invalid opening.bnr size: %0lx",
|
||||
(unsigned long)FileSize);
|
||||
}
|
||||
|
||||
|
||||
CBannerLoaderGC::~CBannerLoaderGC()
|
||||
{
|
||||
if (m_pBannerFile)
|
||||
{
|
||||
delete [] m_pBannerFile;
|
||||
m_pBannerFile = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<u32> CBannerLoaderGC::GetBanner(int* pWidth, int* pHeight)
|
||||
{
|
||||
std::vector<u32> Buffer;
|
||||
Buffer.resize(DVD_BANNER_WIDTH * DVD_BANNER_HEIGHT);
|
||||
auto const pBanner = (DVDBanner*)m_pBannerFile;
|
||||
ColorUtil::decode5A3image(&Buffer[0], pBanner->image, DVD_BANNER_WIDTH, DVD_BANNER_HEIGHT);
|
||||
*pWidth = DVD_BANNER_WIDTH;
|
||||
*pHeight = DVD_BANNER_HEIGHT;
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
|
||||
std::map<IVolume::ELanguage, std::string> CBannerLoaderGC::GetNames()
|
||||
{
|
||||
std::map<IVolume::ELanguage, std::string> names;
|
||||
|
||||
if (!IsValid())
|
||||
{
|
||||
return names;
|
||||
}
|
||||
|
||||
u32 name_count = 0;
|
||||
IVolume::ELanguage language;
|
||||
bool is_japanese = m_country == IVolume::ECountry::COUNTRY_JAPAN;
|
||||
|
||||
// find Banner type
|
||||
switch (m_BNRType)
|
||||
{
|
||||
case CBannerLoaderGC::BANNER_BNR1:
|
||||
name_count = 1;
|
||||
language = is_japanese ? IVolume::ELanguage::LANGUAGE_JAPANESE : IVolume::ELanguage::LANGUAGE_ENGLISH;
|
||||
break;
|
||||
|
||||
// English, German, French, Spanish, Italian, Dutch
|
||||
case CBannerLoaderGC::BANNER_BNR2:
|
||||
name_count = 6;
|
||||
language = IVolume::ELanguage::LANGUAGE_ENGLISH;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
auto const banner = reinterpret_cast<const DVDBanner*>(m_pBannerFile);
|
||||
|
||||
for (u32 i = 0; i < name_count; ++i)
|
||||
{
|
||||
auto& comment = banner->comment[i];
|
||||
std::string name = GetDecodedString(comment.longTitle);
|
||||
|
||||
if (name.empty())
|
||||
name = GetDecodedString(comment.shortTitle);
|
||||
|
||||
if (!name.empty())
|
||||
names[(IVolume::ELanguage)(language + i)] = name;
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
|
||||
std::string CBannerLoaderGC::GetCompany()
|
||||
{
|
||||
std::string company;
|
||||
|
||||
if (IsValid())
|
||||
{
|
||||
auto const pBanner = (DVDBanner*)m_pBannerFile;
|
||||
auto& data = pBanner->comment[0].shortMaker;
|
||||
company = GetDecodedString(data);
|
||||
}
|
||||
|
||||
return company;
|
||||
}
|
||||
|
||||
|
||||
std::map<IVolume::ELanguage, std::string> CBannerLoaderGC::GetDescriptions()
|
||||
{
|
||||
std::map<IVolume::ELanguage, std::string> descriptions;
|
||||
|
||||
if (!IsValid())
|
||||
{
|
||||
return descriptions;
|
||||
}
|
||||
|
||||
u32 desc_count = 0;
|
||||
IVolume::ELanguage language;
|
||||
bool is_japanese = m_country == IVolume::ECountry::COUNTRY_JAPAN;
|
||||
|
||||
// find Banner type
|
||||
switch (m_BNRType)
|
||||
{
|
||||
case CBannerLoaderGC::BANNER_BNR1:
|
||||
desc_count = 1;
|
||||
language = is_japanese ? IVolume::ELanguage::LANGUAGE_JAPANESE : IVolume::ELanguage::LANGUAGE_ENGLISH;
|
||||
break;
|
||||
|
||||
// English, German, French, Spanish, Italian, Dutch
|
||||
case CBannerLoaderGC::BANNER_BNR2:
|
||||
language = IVolume::ELanguage::LANGUAGE_ENGLISH;
|
||||
desc_count = 6;
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
auto banner = reinterpret_cast<const DVDBanner*>(m_pBannerFile);
|
||||
|
||||
for (u32 i = 0; i < desc_count; ++i)
|
||||
{
|
||||
auto& data = banner->comment[i].comment;
|
||||
std::string description = GetDecodedString(data);
|
||||
|
||||
if (!description.empty())
|
||||
descriptions[(IVolume::ELanguage)(language + i)] = description;
|
||||
}
|
||||
|
||||
return descriptions;
|
||||
}
|
||||
|
||||
CBannerLoaderGC::BANNER_TYPE CBannerLoaderGC::getBannerType()
|
||||
{
|
||||
u32 bannerSignature = *(u32*)m_pBannerFile;
|
||||
switch (bannerSignature)
|
||||
{
|
||||
case 0x31524e42: // "BNR1"
|
||||
return CBannerLoaderGC::BANNER_BNR1;
|
||||
case 0x32524e42: // "BNR2"
|
||||
return CBannerLoaderGC::BANNER_BNR2;
|
||||
default:
|
||||
return CBannerLoaderGC::BANNER_UNKNOWN;
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace
|
@ -1,87 +0,0 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <cstring>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
|
||||
#include "DiscIO/BannerLoader.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
#include "DiscIO/VolumeGC.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
|
||||
class IFileSystem;
|
||||
|
||||
class CBannerLoaderGC
|
||||
: public IBannerLoader
|
||||
{
|
||||
public:
|
||||
CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume* volume);
|
||||
virtual ~CBannerLoaderGC();
|
||||
|
||||
virtual std::vector<u32> GetBanner(int* pWidth, int* pHeight) override;
|
||||
|
||||
virtual std::map<IVolume::ELanguage, std::string> GetNames() override;
|
||||
virtual std::string GetCompany() override;
|
||||
virtual std::map<IVolume::ELanguage, std::string> GetDescriptions() override;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
DVD_BANNER_WIDTH = 96,
|
||||
DVD_BANNER_HEIGHT = 32
|
||||
};
|
||||
|
||||
enum BANNER_TYPE
|
||||
{
|
||||
BANNER_UNKNOWN,
|
||||
BANNER_BNR1,
|
||||
BANNER_BNR2,
|
||||
};
|
||||
|
||||
// Banner Comment
|
||||
struct DVDBannerComment
|
||||
{
|
||||
char shortTitle[32]; // Short game title shown in IPL menu
|
||||
char shortMaker[32]; // Short developer, publisher names shown in IPL menu
|
||||
char longTitle[64]; // Long game title shown in IPL game start screen
|
||||
char longMaker[64]; // Long developer, publisher names shown in IPL game start screen
|
||||
char comment[128]; // Game description shown in IPL game start screen in two lines.
|
||||
};
|
||||
|
||||
// "opening.bnr" file format for EU console
|
||||
struct DVDBanner
|
||||
{
|
||||
u32 id; // 'BNR2'
|
||||
u32 padding[7];
|
||||
u16 image[DVD_BANNER_WIDTH * DVD_BANNER_HEIGHT]; // RGB5A3 96x32 texture image
|
||||
DVDBannerComment comment[6]; // Comments in six languages (only 1 for BNR1 type)
|
||||
};
|
||||
|
||||
static const u32 BNR1_SIZE = sizeof(DVDBanner) - sizeof(DVDBannerComment) * 5;
|
||||
static const u32 BNR2_SIZE = sizeof(DVDBanner);
|
||||
|
||||
template <u32 N>
|
||||
std::string GetDecodedString(const char (&data)[N])
|
||||
{
|
||||
auto const string_decoder = CVolumeGC::GetStringDecoder(m_country);
|
||||
|
||||
// strnlen to trim NULLs
|
||||
return string_decoder(std::string(data, strnlen(data, sizeof(data))));
|
||||
}
|
||||
|
||||
BANNER_TYPE m_BNRType;
|
||||
BANNER_TYPE getBannerType();
|
||||
|
||||
DiscIO::IVolume::ECountry const m_country;
|
||||
};
|
||||
|
||||
} // namespace
|
@ -1,122 +0,0 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#include <algorithm>
|
||||
#include <cstddef>
|
||||
#include <cstdio>
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/ColorUtil.h"
|
||||
#include "Common/CommonFuncs.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
#include "DiscIO/BannerLoaderWii.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
|
||||
CBannerLoaderWii::CBannerLoaderWii(DiscIO::IVolume *pVolume)
|
||||
{
|
||||
u64 TitleID = 0;
|
||||
pVolume->GetTitleID((u8*)&TitleID);
|
||||
TitleID = Common::swap64(TitleID);
|
||||
|
||||
std::string Filename = StringFromFormat("%stitle/%08x/%08x/data/banner.bin",
|
||||
File::GetUserPath(D_WIIUSER_IDX).c_str(), (u32)(TitleID>>32), (u32)TitleID);
|
||||
|
||||
if (!File::Exists(Filename))
|
||||
{
|
||||
m_IsValid = false;
|
||||
return;
|
||||
}
|
||||
|
||||
// load the banner.bin
|
||||
size_t FileSize = (size_t) File::GetSize(Filename);
|
||||
|
||||
if (FileSize > 0)
|
||||
{
|
||||
m_pBannerFile = new u8[FileSize];
|
||||
File::IOFile pFile(Filename, "rb");
|
||||
if (pFile)
|
||||
{
|
||||
pFile.ReadBytes(m_pBannerFile, FileSize);
|
||||
m_IsValid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
CBannerLoaderWii::~CBannerLoaderWii()
|
||||
{
|
||||
if (m_pBannerFile)
|
||||
{
|
||||
delete [] m_pBannerFile;
|
||||
m_pBannerFile = nullptr;
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<u32> CBannerLoaderWii::GetBanner(int* pWidth, int* pHeight)
|
||||
{
|
||||
SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile;
|
||||
std::vector<u32> Buffer;
|
||||
Buffer.resize(192 * 64);
|
||||
ColorUtil::decode5A3image(&Buffer[0], (u16*)pBanner->m_BannerTexture, 192, 64);
|
||||
*pWidth = 192;
|
||||
*pHeight = 64;
|
||||
return Buffer;
|
||||
}
|
||||
|
||||
bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::string& result)
|
||||
{
|
||||
if (IsValid())
|
||||
{
|
||||
auto const banner = reinterpret_cast<const SWiiBanner*>(m_pBannerFile);
|
||||
auto const src_ptr = banner->m_Comment[index];
|
||||
|
||||
// Trim at first nullptr
|
||||
auto const length = std::find(src_ptr, src_ptr + COMMENT_SIZE, 0x0) - src_ptr;
|
||||
|
||||
std::wstring src;
|
||||
src.resize(length);
|
||||
std::transform(src_ptr, src_ptr + src.size(), src.begin(), (u16(&)(u16))Common::swap16);
|
||||
result = UTF16ToUTF8(src);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
std::map<IVolume::ELanguage, std::string> CBannerLoaderWii::GetNames()
|
||||
{
|
||||
std::map<IVolume::ELanguage, std::string> result;
|
||||
|
||||
std::string name;
|
||||
if (GetStringFromComments(NAME_IDX, name))
|
||||
result[IVolume::ELanguage::LANGUAGE_UNKNOWN] = name;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
std::string CBannerLoaderWii::GetCompany()
|
||||
{
|
||||
return "";
|
||||
}
|
||||
|
||||
std::map<IVolume::ELanguage, std::string> CBannerLoaderWii::GetDescriptions()
|
||||
{
|
||||
std::map<IVolume::ELanguage, std::string> result;
|
||||
|
||||
std::string name;
|
||||
if (GetStringFromComments(DESC_IDX, name))
|
||||
result[IVolume::ELanguage::LANGUAGE_UNKNOWN] = name;
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
} // namespace
|
@ -1,64 +0,0 @@
|
||||
// Copyright 2013 Dolphin Emulator Project
|
||||
// Licensed under GPLv2
|
||||
// Refer to the license.txt file included.
|
||||
|
||||
#pragma once
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "DiscIO/BannerLoader.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
|
||||
class IVolume;
|
||||
|
||||
class CBannerLoaderWii
|
||||
: public IBannerLoader
|
||||
{
|
||||
public:
|
||||
CBannerLoaderWii(DiscIO::IVolume *pVolume);
|
||||
|
||||
virtual ~CBannerLoaderWii();
|
||||
|
||||
virtual std::vector<u32> GetBanner(int* pWidth, int* pHeight) override;
|
||||
|
||||
virtual std::map<IVolume::ELanguage, std::string> GetNames() override;
|
||||
virtual std::string GetCompany() override;
|
||||
virtual std::map<IVolume::ELanguage, std::string> GetDescriptions() override;
|
||||
|
||||
private:
|
||||
enum
|
||||
{
|
||||
TEXTURE_SIZE = 192 * 64 * 2,
|
||||
ICON_SIZE = 48 * 48 * 2,
|
||||
COMMENT_SIZE = 32
|
||||
};
|
||||
|
||||
enum CommentIndex
|
||||
{
|
||||
NAME_IDX,
|
||||
DESC_IDX
|
||||
};
|
||||
|
||||
struct SWiiBanner
|
||||
{
|
||||
u32 ID;
|
||||
|
||||
u32 m_Flag;
|
||||
u16 m_Speed;
|
||||
u8 m_Unknown[22];
|
||||
|
||||
// Not null terminated!
|
||||
u16 m_Comment[2][COMMENT_SIZE];
|
||||
u8 m_BannerTexture[TEXTURE_SIZE];
|
||||
u8 m_IconTexture[8][ICON_SIZE];
|
||||
};
|
||||
|
||||
bool GetStringFromComments(const CommentIndex index, std::string& s);
|
||||
};
|
||||
|
||||
} // namespace
|
@ -1,7 +1,4 @@
|
||||
set(SRCS BannerLoader.cpp
|
||||
BannerLoaderGC.cpp
|
||||
BannerLoaderWii.cpp
|
||||
Blob.cpp
|
||||
set(SRCS Blob.cpp
|
||||
CISOBlob.cpp
|
||||
WbfsBlob.cpp
|
||||
CompressedBlob.cpp
|
||||
|
@ -35,9 +35,6 @@
|
||||
</ImportGroup>
|
||||
<PropertyGroup Label="UserMacros" />
|
||||
<ItemGroup>
|
||||
<ClCompile Include="BannerLoader.cpp" />
|
||||
<ClCompile Include="BannerLoaderGC.cpp" />
|
||||
<ClCompile Include="BannerLoaderWii.cpp" />
|
||||
<ClCompile Include="Blob.cpp" />
|
||||
<ClCompile Include="CISOBlob.cpp" />
|
||||
<ClCompile Include="CompressedBlob.cpp" />
|
||||
@ -58,9 +55,6 @@
|
||||
<ClCompile Include="WiiWad.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="BannerLoader.h" />
|
||||
<ClInclude Include="BannerLoaderGC.h" />
|
||||
<ClInclude Include="BannerLoaderWii.h" />
|
||||
<ClInclude Include="Blob.h" />
|
||||
<ClInclude Include="CISOBlob.h" />
|
||||
<ClInclude Include="CompressedBlob.h" />
|
||||
|
@ -24,15 +24,6 @@
|
||||
<ClCompile Include="DiscScrubber.cpp">
|
||||
<Filter>DiscScrubber</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BannerLoader.cpp">
|
||||
<Filter>FileHandler</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BannerLoaderGC.cpp">
|
||||
<Filter>FileHandler</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="BannerLoaderWii.cpp">
|
||||
<Filter>FileHandler</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="Filesystem.cpp">
|
||||
<Filter>FileSystem</Filter>
|
||||
</ClCompile>
|
||||
@ -89,15 +80,6 @@
|
||||
<ClInclude Include="DiscScrubber.h">
|
||||
<Filter>DiscScrubber</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BannerLoaderWii.h">
|
||||
<Filter>FileHandler</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BannerLoader.h">
|
||||
<Filter>FileHandler</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="BannerLoaderGC.h">
|
||||
<Filter>FileHandler</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Filesystem.h">
|
||||
<Filter>FileSystem</Filter>
|
||||
</ClInclude>
|
||||
|
@ -11,6 +11,7 @@
|
||||
|
||||
#include "Common/CommonFuncs.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/StringUtil.h"
|
||||
|
||||
namespace DiscIO
|
||||
{
|
||||
@ -74,10 +75,12 @@ public:
|
||||
}
|
||||
virtual std::string GetUniqueID() const = 0;
|
||||
virtual std::string GetMakerID() const = 0;
|
||||
virtual int GetRevision() const { return 0; }
|
||||
// TODO: eliminate?
|
||||
virtual std::string GetName() const;
|
||||
virtual int GetRevision() const = 0;
|
||||
virtual std::string GetName() const = 0;
|
||||
virtual std::map<ELanguage, std::string> GetNames() const = 0;
|
||||
virtual std::map<ELanguage, std::string> GetDescriptions() const { return std::map<ELanguage, std::string>(); }
|
||||
virtual std::string GetCompany() const { return std::string(); }
|
||||
virtual std::vector<u32> GetBanner(int* width, int* height) const;
|
||||
virtual u32 GetFSTSize() const = 0;
|
||||
virtual std::string GetApploaderDate() const = 0;
|
||||
|
||||
@ -93,6 +96,23 @@ public:
|
||||
|
||||
// Size on disc (compressed size)
|
||||
virtual u64 GetRawSize() const = 0;
|
||||
|
||||
protected:
|
||||
template <u32 N>
|
||||
std::string DecodeString(const char(&data)[N]) const
|
||||
{
|
||||
// strnlen to trim NULLs
|
||||
std::string string(data, strnlen(data, sizeof(data)));
|
||||
|
||||
// There don't seem to be any GC discs with the country set to Taiwan...
|
||||
// But maybe they would use Shift_JIS if they existed? Not sure
|
||||
bool use_shift_jis = (COUNTRY_JAPAN == GetCountry() || COUNTRY_TAIWAN == GetCountry());
|
||||
|
||||
if (use_shift_jis)
|
||||
return SHIFTJISToUTF8(string);
|
||||
else
|
||||
return CP1252ToUTF8(string);
|
||||
}
|
||||
};
|
||||
|
||||
// Generic Switch function for all volumes
|
||||
|
@ -4,15 +4,59 @@
|
||||
|
||||
#include <map>
|
||||
#include <string>
|
||||
#include <utility>
|
||||
#include <vector>
|
||||
|
||||
#include "Common/ColorUtil.h"
|
||||
#include "Common/CommonFuncs.h"
|
||||
#include "Common/CommonTypes.h"
|
||||
#include "Common/FileUtil.h"
|
||||
#include "Common/StringUtil.h"
|
||||
#include "Common/Logging/Log.h"
|
||||
#include "DiscIO/Volume.h"
|
||||
|
||||
// Increment CACHE_REVISION if the code below is modified (ISOFile.cpp & GameFile.cpp)
|
||||
namespace DiscIO
|
||||
{
|
||||
|
||||
static const unsigned int WII_BANNER_WIDTH = 192;
|
||||
static const unsigned int WII_BANNER_HEIGHT = 64;
|
||||
static const unsigned int WII_BANNER_SIZE = WII_BANNER_WIDTH * WII_BANNER_HEIGHT * 2;
|
||||
static const unsigned int WII_BANNER_OFFSET = 0xA0;
|
||||
|
||||
std::vector<u32> IVolume::GetBanner(int* width, int* height) const
|
||||
{
|
||||
*width = 0;
|
||||
*height = 0;
|
||||
|
||||
u64 TitleID = 0;
|
||||
GetTitleID((u8*)&TitleID);
|
||||
TitleID = Common::swap64(TitleID);
|
||||
|
||||
std::string file_name = StringFromFormat("%stitle/%08x/%08x/data/banner.bin",
|
||||
File::GetUserPath(D_WIIUSER_IDX).c_str(), (u32)(TitleID >> 32), (u32)TitleID);
|
||||
if (!File::Exists(file_name))
|
||||
return std::vector<u32>();
|
||||
|
||||
if (File::GetSize(file_name) < WII_BANNER_OFFSET + WII_BANNER_SIZE)
|
||||
return std::vector<u32>();
|
||||
|
||||
File::IOFile file(file_name, "rb");
|
||||
if (!file.Seek(WII_BANNER_OFFSET, SEEK_SET))
|
||||
return std::vector<u32>();
|
||||
|
||||
std::vector<u8> banner_file(WII_BANNER_SIZE);
|
||||
if (!file.ReadBytes(banner_file.data(), banner_file.size()))
|
||||
return std::vector<u32>();
|
||||
|
||||
std::vector<u32> image_buffer(WII_BANNER_WIDTH * WII_BANNER_HEIGHT);
|
||||
ColorUtil::decode5A3image(image_buffer.data(), (u16*)banner_file.data(), WII_BANNER_WIDTH, WII_BANNER_HEIGHT);
|
||||
|
||||
*width = WII_BANNER_WIDTH;
|
||||
*height = WII_BANNER_HEIGHT;
|
||||
return image_buffer;
|
||||
}
|
||||
|
||||
// Increment CACHE_REVISION if the code below is modified (ISOFile.cpp & GameFile.cpp)
|
||||
IVolume::ECountry CountrySwitch(u8 country_code)
|
||||
{
|
||||
switch (country_code)
|
||||
@ -99,13 +143,4 @@ u8 GetSysMenuRegion(u16 _TitleVersion)
|
||||
}
|
||||
}
|
||||
|
||||
std::string IVolume::GetName() const
|
||||
{
|
||||
auto names = GetNames();
|
||||
if (names.empty())
|
||||
return "";
|
||||
else
|
||||
return names.cbegin()->second;
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -182,10 +182,21 @@ std::string CVolumeDirectory::GetMakerID() const
|
||||
return "VOID";
|
||||
}
|
||||
|
||||
std::string CVolumeDirectory::GetName() const
|
||||
{
|
||||
char name[0x60];
|
||||
if (Read(0x20, 0x60, (u8*)name, false))
|
||||
return DecodeString(name);
|
||||
else
|
||||
return "";
|
||||
}
|
||||
|
||||
std::map<IVolume::ELanguage, std::string> CVolumeDirectory::GetNames() const
|
||||
{
|
||||
std::map<IVolume::ELanguage, std::string> names;
|
||||
names[IVolume::ELanguage::LANGUAGE_UNKNOWN] = (char*)(&m_diskHeader[0x20]);
|
||||
std::string name = GetName();
|
||||
if (!name.empty())
|
||||
names[IVolume::ELanguage::LANGUAGE_UNKNOWN] = name;
|
||||
return names;
|
||||
}
|
||||
|
||||
|
@ -39,6 +39,8 @@ public:
|
||||
|
||||
std::string GetMakerID() const override;
|
||||
|
||||
int GetRevision() const override { return 0; }
|
||||
std::string GetName() const override;
|
||||
std::map<IVolume::ELanguage, std::string> GetNames() const override;
|
||||
void SetName(const std::string&);
|
||||
|
||||
|
@ -8,10 +8,13 @@
|
||||
#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"
|
||||
|
||||
@ -93,19 +96,133 @@ int CVolumeGC::GetRevision() const
|
||||
return revision;
|
||||
}
|
||||
|
||||
std::string CVolumeGC::GetName() 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() const
|
||||
{
|
||||
std::map<IVolume::ELanguage, std::string> names;
|
||||
|
||||
auto const string_decoder = GetStringDecoder(GetCountry());
|
||||
if (!LoadBannerFile())
|
||||
return names;
|
||||
|
||||
char name[0x60 + 1] = {};
|
||||
if (m_pReader != nullptr && Read(0x20, 0x60, (u8*)name))
|
||||
names[IVolume::ELanguage::LANGUAGE_UNKNOWN] = string_decoder(name);
|
||||
u32 name_count = 0;
|
||||
IVolume::ELanguage language;
|
||||
bool is_japanese = GetCountry() == IVolume::ECountry::COUNTRY_JAPAN;
|
||||
|
||||
switch (m_banner_file_type)
|
||||
{
|
||||
case BANNER_BNR1:
|
||||
name_count = 1;
|
||||
language = is_japanese ? IVolume::ELanguage::LANGUAGE_JAPANESE : IVolume::ELanguage::LANGUAGE_ENGLISH;
|
||||
break;
|
||||
|
||||
case BANNER_BNR2:
|
||||
name_count = 6;
|
||||
language = IVolume::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 < name_count; ++i)
|
||||
{
|
||||
auto& comment = banner->comment[i];
|
||||
std::string name = DecodeString(comment.longTitle);
|
||||
|
||||
if (name.empty())
|
||||
name = DecodeString(comment.shortTitle);
|
||||
|
||||
if (!name.empty())
|
||||
names[(IVolume::ELanguage)(language + i)] = name;
|
||||
}
|
||||
|
||||
return names;
|
||||
}
|
||||
|
||||
std::map<IVolume::ELanguage, std::string> CVolumeGC::GetDescriptions() const
|
||||
{
|
||||
std::map<IVolume::ELanguage, std::string> descriptions;
|
||||
|
||||
if (!LoadBannerFile())
|
||||
return descriptions;
|
||||
|
||||
u32 desc_count = 0;
|
||||
IVolume::ELanguage language;
|
||||
bool is_japanese = GetCountry() == IVolume::ECountry::COUNTRY_JAPAN;
|
||||
|
||||
switch (m_banner_file_type)
|
||||
{
|
||||
case BANNER_BNR1:
|
||||
desc_count = 1;
|
||||
language = is_japanese ? IVolume::ELanguage::LANGUAGE_JAPANESE : IVolume::ELanguage::LANGUAGE_ENGLISH;
|
||||
break;
|
||||
|
||||
case BANNER_BNR2:
|
||||
language = IVolume::ELanguage::LANGUAGE_ENGLISH;
|
||||
desc_count = 6;
|
||||
break;
|
||||
|
||||
case BANNER_INVALID:
|
||||
case BANNER_NOT_LOADED:
|
||||
break;
|
||||
}
|
||||
|
||||
auto banner = reinterpret_cast<const GCBanner*>(m_banner_file.data());
|
||||
|
||||
for (u32 i = 0; i < desc_count; ++i)
|
||||
{
|
||||
auto& data = banner->comment[i].comment;
|
||||
std::string description = DecodeString(data);
|
||||
|
||||
if (!description.empty())
|
||||
descriptions[(IVolume::ELanguage)(language + i)] = description;
|
||||
}
|
||||
|
||||
return descriptions;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
u32 CVolumeGC::GetFSTSize() const
|
||||
{
|
||||
if (m_pReader == nullptr)
|
||||
@ -155,10 +272,46 @@ bool CVolumeGC::IsDiscTwo() const
|
||||
return (disc_two_check == 1);
|
||||
}
|
||||
|
||||
CVolumeGC::StringDecoder CVolumeGC::GetStringDecoder(ECountry country)
|
||||
bool CVolumeGC::LoadBannerFile() const
|
||||
{
|
||||
return (COUNTRY_JAPAN == country || COUNTRY_TAIWAN == country) ?
|
||||
SHIFTJISToUTF8 : CP1252ToUTF8;
|
||||
// The methods GetNames, GetDescriptions, GetCompany and GetBanner
|
||||
// all need to access the opening.bnr file. These four methods are
|
||||
// typically called after each other, so we store the file in RAM
|
||||
// to avoid reading it from the disc several times. However,
|
||||
// if none of these methods are called, the file is never loaded.
|
||||
|
||||
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();
|
||||
switch (bannerSignature)
|
||||
{
|
||||
case 0x31524e42: // "BNR1"
|
||||
m_banner_file_type = BANNER_BNR1;
|
||||
break;
|
||||
case 0x32524e42: // "BNR2"
|
||||
m_banner_file_type = BANNER_BNR2;
|
||||
break;
|
||||
default:
|
||||
m_banner_file_type = BANNER_INVALID;
|
||||
WARN_LOG(DISCIO, "Invalid opening.bnr type");
|
||||
break;
|
||||
}
|
||||
}
|
||||
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;
|
||||
}
|
||||
|
||||
} // namespace
|
||||
|
@ -28,7 +28,11 @@ public:
|
||||
std::string GetUniqueID() const override;
|
||||
std::string GetMakerID() const override;
|
||||
int GetRevision() const override;
|
||||
std::map<IVolume::ELanguage, std::string> GetNames() const override;
|
||||
virtual std::string GetName() const override;
|
||||
std::map<ELanguage, std::string> GetNames() const override;
|
||||
std::map<ELanguage, std::string> GetDescriptions() const override;
|
||||
std::string GetCompany() const override;
|
||||
std::vector<u32> GetBanner(int* width, int* height) const override;
|
||||
u32 GetFSTSize() const override;
|
||||
std::string GetApploaderDate() const override;
|
||||
|
||||
@ -38,11 +42,44 @@ public:
|
||||
u64 GetSize() const override;
|
||||
u64 GetRawSize() const override;
|
||||
|
||||
typedef std::string(*StringDecoder)(const std::string&);
|
||||
|
||||
static StringDecoder GetStringDecoder(ECountry country);
|
||||
|
||||
private:
|
||||
bool LoadBannerFile() const;
|
||||
|
||||
static const int GC_BANNER_WIDTH = 96;
|
||||
static const int GC_BANNER_HEIGHT = 32;
|
||||
|
||||
// Banner Comment
|
||||
struct GCBannerComment
|
||||
{
|
||||
char shortTitle[32]; // Short game title shown in IPL menu
|
||||
char shortMaker[32]; // Short developer, publisher names shown in IPL menu
|
||||
char longTitle[64]; // Long game title shown in IPL game start screen
|
||||
char longMaker[64]; // Long developer, publisher names shown in IPL game start screen
|
||||
char comment[128]; // Game description shown in IPL game start screen in two lines.
|
||||
};
|
||||
|
||||
struct GCBanner
|
||||
{
|
||||
u32 id; // "BNR1" for NTSC, "BNR2" for PAL
|
||||
u32 padding[7];
|
||||
u16 image[GC_BANNER_WIDTH * GC_BANNER_HEIGHT]; // RGB5A3 96x32 image
|
||||
GCBannerComment comment[6]; // Comments in six languages (only one for BNR1 type)
|
||||
};
|
||||
|
||||
static const size_t BNR1_SIZE = sizeof(GCBanner) - sizeof(GCBannerComment) * 5;
|
||||
static const size_t BNR2_SIZE = sizeof(GCBanner);
|
||||
|
||||
enum BannerFileType
|
||||
{
|
||||
BANNER_NOT_LOADED,
|
||||
BANNER_INVALID,
|
||||
BANNER_BNR1,
|
||||
BANNER_BNR2
|
||||
};
|
||||
|
||||
mutable BannerFileType m_banner_file_type = BANNER_NOT_LOADED;
|
||||
mutable std::vector<u8> m_banner_file;
|
||||
|
||||
std::unique_ptr<IBlobReader> m_pReader;
|
||||
};
|
||||
|
||||
|
@ -31,9 +31,10 @@ public:
|
||||
std::string GetUniqueID() const override;
|
||||
std::string GetMakerID() const override;
|
||||
int GetRevision() const override;
|
||||
std::string GetName() const override { return ""; }
|
||||
std::map<IVolume::ELanguage, std::string> GetNames() const override;
|
||||
u32 GetFSTSize() const override { return 0; }
|
||||
std::string GetApploaderDate() const override { return "0"; }
|
||||
u32 GetFSTSize() const override { return 0; }
|
||||
std::string GetApploaderDate() const override { return ""; }
|
||||
|
||||
bool IsWadFile() const override;
|
||||
|
||||
|
@ -192,16 +192,20 @@ int CVolumeWiiCrypted::GetRevision() const
|
||||
return revision;
|
||||
}
|
||||
|
||||
std::string CVolumeWiiCrypted::GetName() const
|
||||
{
|
||||
char name_buffer[0x60];
|
||||
if (m_pReader != nullptr && Read(0x20, 0x60, (u8*)&name_buffer, false))
|
||||
return DecodeString(name_buffer);
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::map<IVolume::ELanguage, std::string> CVolumeWiiCrypted::GetNames() const
|
||||
{
|
||||
// TODO: Read opening.bnr
|
||||
std::map<IVolume::ELanguage, std::string> names;
|
||||
|
||||
auto const string_decoder = CVolumeGC::GetStringDecoder(GetCountry());
|
||||
|
||||
char name[0xFF] = {};
|
||||
if (m_pReader != nullptr && Read(0x20, 0x60, (u8*)&name, true))
|
||||
names[IVolume::ELanguage::LANGUAGE_UNKNOWN] = string_decoder(name);
|
||||
|
||||
names[IVolume::ELanguage::LANGUAGE_UNKNOWN] = GetName();
|
||||
return names;
|
||||
}
|
||||
|
||||
|
@ -31,6 +31,7 @@ public:
|
||||
std::string GetUniqueID() const override;
|
||||
std::string GetMakerID() const override;
|
||||
int GetRevision() const override;
|
||||
std::string GetName() const override;
|
||||
std::map<IVolume::ELanguage, std::string> GetNames() const override;
|
||||
u32 GetFSTSize() const override;
|
||||
std::string GetApploaderDate() const override;
|
||||
|
Reference in New Issue
Block a user