Fix what I broke.

This commit is contained in:
Jordan Woyak 2013-03-02 22:57:49 -06:00
parent 88cb11ba0a
commit aeb4fc9846
9 changed files with 108 additions and 151 deletions

View File

@ -17,13 +17,19 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <algorithm>
#include "Common.h" #include "Common.h"
#include "CommonPaths.h" #include "CommonPaths.h"
#include "StringUtil.h" #include "StringUtil.h"
#ifdef _WIN32 #ifdef _WIN32
#include <Windows.h> #include <Windows.h>
#elif defined(ANDROID)
#else
#include <iconv.h>
#include <errno.h>
#endif #endif
// faster than sscanf // faster than sscanf
@ -418,18 +424,80 @@ std::string SHIFTJISToUTF8(const std::string& input)
return UTF16ToUTF8(CPToUTF16(932, input)); return UTF16ToUTF8(CPToUTF16(932, input));
} }
std::string CP1252ToUTF8(const std::string& input)
{
return UTF16ToUTF8(CPToUTF16(1252, input));
}
#else #else
std::string UTF16ToUTF8(const std::wstring& input) template <typename T>
std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& input)
{ {
// TODO: implement std::string result;
return std::string();
#if defined(ANDROID)
result = "Not implemented on Android!";
#else
iconv_t const conv_desc = iconv_open("UTF-8", fromcode);
if ((iconv_t)-1 == conv_desc)
{
ERROR_LOG(COMMON, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno));
}
else
{
size_t const in_bytes = sizeof(T) * input.size();
size_t const out_buffer_size = 4 * in_bytes;
std::string out_buffer;
out_buffer.resize(out_buffer_size);
auto src_buffer = &input[0];
size_t src_bytes = in_bytes;
auto dst_buffer = &out_buffer[0];
size_t dst_bytes = out_buffer.size();
size_t const iconv_size = iconv(conv_desc, (char**)(&src_buffer), &src_bytes,
&dst_buffer, &dst_bytes);
if ((size_t)-1 == iconv_size)
{
ERROR_LOG(COMMON, "iconv failure [%s]: %s", fromcode, strerror(errno));
}
else
{
out_buffer.resize(out_buffer_size - dst_bytes);
out_buffer.swap(result);
// TODO: why is this needed?
result.erase(std::remove(result.begin(), result.end(), 0x00), result.end());
}
iconv_close(conv_desc);
}
#endif
return result;
}
std::string CP1252ToUTF8(const std::string& input)
{
return CodeToUTF8("CP1252", input);
} }
std::string SHIFTJISToUTF8(const std::string& input) std::string SHIFTJISToUTF8(const std::string& input)
{ {
// TODO: implement //return CodeToUTF8("CP932", input);
return std::string(); return CodeToUTF8("SJIS", input);
}
std::string UTF16ToUTF8(const std::wstring& input)
{
//return CodeToUTF8("UCS-2", input);
//return CodeToUTF8("UCS-2LE", input);
//return CodeToUTF8("UTF-16", input);
return CodeToUTF8("UTF-16LE", input);
} }
#endif #endif

View File

@ -97,6 +97,7 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
std::string UriDecode(const std::string & sSrc); std::string UriDecode(const std::string & sSrc);
std::string UriEncode(const std::string & sSrc); std::string UriEncode(const std::string & sSrc);
std::string CP1252ToUTF8(const std::string& str);
std::string SHIFTJISToUTF8(const std::string& str); std::string SHIFTJISToUTF8(const std::string& str);
std::string UTF16ToUTF8(const std::wstring& str); std::string UTF16ToUTF8(const std::wstring& str);

View File

@ -31,9 +31,9 @@ IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVo
{ {
return new CBannerLoaderWii(pVolume); return new CBannerLoaderWii(pVolume);
} }
if (_rFileSystem.IsValid()) if (_rFileSystem.IsValid())
{ {
return new CBannerLoaderGC(_rFileSystem); return new CBannerLoaderGC(_rFileSystem, pVolume);
} }
return NULL; return NULL;

View File

@ -44,12 +44,6 @@ class IBannerLoader
virtual std::vector<std::string> GetNames() = 0; virtual std::vector<std::string> GetNames() = 0;
virtual std::string GetCompany() = 0; virtual std::string GetCompany() = 0;
virtual std::vector<std::string> GetDescriptions() = 0; virtual std::vector<std::string> GetDescriptions() = 0;
private:
u16 swap16(u16 data)
{
return ((data & 0xff00) >> 8) | ((data & 0xff) << 8);
}
}; };
IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume *pVolume); IBannerLoader* CreateBannerLoader(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume *pVolume);

View File

@ -23,9 +23,10 @@
namespace DiscIO namespace DiscIO
{ {
CBannerLoaderGC::CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem) CBannerLoaderGC::CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume* volume)
: m_pBannerFile(NULL), : m_pBannerFile(NULL)
m_IsValid(false) , m_IsValid(false)
, m_country(volume->GetCountry())
{ {
// load the opening.bnr // load the opening.bnr
size_t FileSize = (size_t) _rFileSystem.GetFileSize("opening.bnr"); size_t FileSize = (size_t) _rFileSystem.GetFileSize("opening.bnr");
@ -104,7 +105,7 @@ std::vector<std::string> CBannerLoaderGC::GetNames()
auto const banner = reinterpret_cast<const DVDBanner*>(m_pBannerFile); auto const banner = reinterpret_cast<const DVDBanner*>(m_pBannerFile);
for (int i = 0; i != name_count; ++i) for (u32 i = 0; i != name_count; ++i)
{ {
auto& comment = banner->comment[i]; auto& comment = banner->comment[i];
@ -167,7 +168,7 @@ std::vector<std::string> CBannerLoaderGC::GetDescriptions()
auto banner = reinterpret_cast<const DVDBanner*>(m_pBannerFile); auto banner = reinterpret_cast<const DVDBanner*>(m_pBannerFile);
for (int i = 0; i != desc_count; ++i) for (u32 i = 0; i != desc_count; ++i)
{ {
auto& data = banner->comment[i].comment; auto& data = banner->comment[i].comment;
descriptions.push_back(GetDecodedString(data)); descriptions.push_back(GetDecodedString(data));

View File

@ -19,6 +19,7 @@
#define _BANNER_LOADER_GC_H_ #define _BANNER_LOADER_GC_H_
#include "BannerLoader.h" #include "BannerLoader.h"
#include "StringUtil.h"
namespace DiscIO namespace DiscIO
{ {
@ -26,7 +27,7 @@ class CBannerLoaderGC
: public IBannerLoader : public IBannerLoader
{ {
public: public:
CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem); CBannerLoaderGC(DiscIO::IFileSystem& _rFileSystem, DiscIO::IVolume* volume);
virtual ~CBannerLoaderGC(); virtual ~CBannerLoaderGC();
virtual bool IsValid(); virtual bool IsValid();
@ -76,8 +77,12 @@ class CBannerLoaderGC
template <u32 N> template <u32 N>
std::string GetDecodedString(const char (&data)[N]) std::string GetDecodedString(const char (&data)[N])
{ {
// Can I always assume SHIFT-JIS? auto const string_decoder = (DiscIO::IVolume::COUNTRY_JAPAN == m_country ||
return SHIFTJISToUTF8(std::string(data, strnlen(data, sizeof(data)))); DiscIO::IVolume::COUNTRY_TAIWAN == m_country) ?
SHIFTJISToUTF8 : CP1252ToUTF8;
// strnlen to trim NULLs
return string_decoder(std::string(data, strnlen(data, sizeof(data))));
} }
u8* m_pBannerFile; u8* m_pBannerFile;
@ -86,6 +91,8 @@ class CBannerLoaderGC
void decode5A3image(u32* dst, u16* src, int width, int height); void decode5A3image(u32* dst, u16* src, int width, int height);
BANNER_TYPE getBannerType(); BANNER_TYPE getBannerType();
DiscIO::IVolume::ECountry const m_country;
}; };
} // namespace } // namespace

View File

@ -25,25 +25,6 @@
#include "FileUtil.h" #include "FileUtil.h"
#include "FileHandlerARC.h" #include "FileHandlerARC.h"
// HyperIris: dunno if this suitable, may be need move.
#ifdef _WIN32
#include <Windows.h>
#else
#include <sys/param.h>
#ifndef ANDROID
#include <iconv.h>
#endif
#include <errno.h>
#endif
#ifndef ICONV_CONST
#if defined __FreeBSD__ || __NetBSD__
#define ICONV_CONST const
#else
#define ICONV_CONST
#endif
#endif
namespace DiscIO namespace DiscIO
{ {
@ -164,35 +145,24 @@ bool CBannerLoaderWii::GetBanner(u32* _pBannerImage)
return true; return true;
} }
bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::string& s) bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::string& result)
{
bool ret = false;
if (IsValid())
{
// find Banner type
SWiiBanner *pBanner = (SWiiBanner*)m_pBannerFile;
// TODO: trim NULLs
ret = CopyBeUnicodeToString(s, pBanner->m_Comment[index], COMMENT_SIZE);
}
return ret;
}
bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::wstring& s)
{ {
if (IsValid()) if (IsValid())
{ {
// find Banner type auto const banner = reinterpret_cast<const SWiiBanner*>(m_pBannerFile);
SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile; auto const src_ptr = banner->m_Comment[index];
std::wstring description; // Trim at first NULL
for (int i = 0; i < COMMENT_SIZE; ++i) auto const length = std::find(src_ptr, src_ptr + COMMENT_SIZE, 0x0) - src_ptr;
description.push_back(Common::swap16(pBanner->m_Comment[index][i]));
std::wstring src;
s = description; src.resize(length);
std::transform(src_ptr, src_ptr + src.size(), src.begin(), (u16(&)(u16))Common::swap16);
result = UTF16ToUTF8(src);
return true; return true;
} }
return false; return false;
} }
@ -237,87 +207,4 @@ void CBannerLoaderWii::decode5A3image(u32* dst, u16* src, int width, int height)
} }
} }
bool CBannerLoaderWii::CopyBeUnicodeToString( std::string& _rDestination, const u16* _src, int length )
{
bool returnCode = false;
#ifdef _WIN32
if (_src)
{
std::wstring src;
src.resize(length);
std::transform(_src, _src + length, &src[0], (u16(&)(u16))Common::swap16);
_rDestination = UTF16ToUTF8(src);
returnCode = true;
}
#else
#ifdef ANDROID
return false;
#else
if (_src)
{
iconv_t conv_desc = iconv_open("UTF-8", "CP932");
if (conv_desc == (iconv_t) -1)
{
// Initialization failure.
if (errno == EINVAL)
{
ERROR_LOG(DISCIO, "Conversion from CP932 to UTF-8 is not supported.");
}
else
{
ERROR_LOG(DISCIO, "Iconv initialization failure: %s\n", strerror (errno));
}
return false;
}
char* src_buffer = new char[length];
for (int i = 0; i < length; i++)
src_buffer[i] = swap16(_src[i]);
size_t inbytes = sizeof(char) * length;
size_t outbytes = 2 * inbytes;
char* utf8_buffer = new char[outbytes + 1];
memset(utf8_buffer, 0, (outbytes + 1) * sizeof(char));
// Save the buffer locations because iconv increments them
char* utf8_buffer_start = utf8_buffer;
char* src_buffer_start = src_buffer;
size_t iconv_size = iconv(conv_desc,
(ICONV_CONST char**)&src_buffer, &inbytes,
&utf8_buffer, &outbytes);
// Handle failures
if (iconv_size == (size_t) -1)
{
ERROR_LOG(DISCIO, "iconv failed.");
switch (errno) {
case EILSEQ:
ERROR_LOG(DISCIO, "Invalid multibyte sequence.");
break;
case EINVAL:
ERROR_LOG(DISCIO, "Incomplete multibyte sequence.");
break;
case E2BIG:
ERROR_LOG(DISCIO, "Insufficient space allocated for output buffer.");
break;
default:
ERROR_LOG(DISCIO, "Error: %s.", strerror(errno));
}
}
else
{
_rDestination = utf8_buffer_start;
returnCode = true;
}
delete[] utf8_buffer_start;
delete[] src_buffer_start;
iconv_close(conv_desc);
}
#endif
#endif
return returnCode;
}
} // namespace } // namespace

View File

@ -75,9 +75,6 @@ class CBannerLoaderWii
void decode5A3image(u32* dst, u16* src, int width, int height); void decode5A3image(u32* dst, u16* src, int width, int height);
bool GetStringFromComments(const CommentIndex index, std::string& s); bool GetStringFromComments(const CommentIndex index, std::string& s);
bool GetStringFromComments(const CommentIndex index, std::wstring& s);
bool CopyBeUnicodeToString(std::string& _rDestination, const u16* _src, int length);
}; };
} // namespace } // namespace

View File

@ -22,6 +22,7 @@
#include <vector> #include <vector>
#include "Common.h" #include "Common.h"
#include "StringUtil.h"
namespace DiscIO namespace DiscIO
{ {
@ -37,6 +38,7 @@ public:
virtual void GetTMD(u8*, u32 *_sz) const { *_sz=0; } virtual void GetTMD(u8*, u32 *_sz) const { *_sz=0; }
virtual std::string GetUniqueID() const = 0; virtual std::string GetUniqueID() const = 0;
virtual std::string GetMakerID() const = 0; virtual std::string GetMakerID() const = 0;
// TODO: eliminate?
virtual std::string GetName() const; virtual std::string GetName() const;
virtual std::vector<std::string> GetNames() const = 0; virtual std::vector<std::string> GetNames() const = 0;
virtual u32 GetFSTSize() const = 0; virtual u32 GetFSTSize() const = 0;