| 
									
										
										
										
											2015-05-24 06:55:12 +02:00
										 |  |  | // Copyright 2009 Dolphin Emulator Project
 | 
					
						
							| 
									
										
										
										
											2015-05-18 01:08:10 +02:00
										 |  |  | // Licensed under GPLv2+
 | 
					
						
							| 
									
										
										
										
											2013-04-17 23:09:55 -04:00
										 |  |  | // Refer to the license.txt file included.
 | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-02-21 01:47:53 +01:00
										 |  |  | #include <cstddef>
 | 
					
						
							| 
									
										
										
										
											2015-09-28 10:57:16 -05:00
										 |  |  | #include <cstring>
 | 
					
						
							| 
									
										
										
										
											2015-04-09 17:44:53 +02:00
										 |  |  | #include <map>
 | 
					
						
							| 
									
										
										
										
											2015-08-31 19:27:18 -04:00
										 |  |  | #include <memory>
 | 
					
						
							| 
									
										
										
										
											2014-02-21 01:47:53 +01:00
										 |  |  | #include <string>
 | 
					
						
							| 
									
										
										
										
											2015-08-31 19:27:18 -04:00
										 |  |  | #include <utility>
 | 
					
						
							| 
									
										
										
										
											2014-02-21 01:47:53 +01:00
										 |  |  | #include <vector>
 | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-09-07 20:06:58 -05:00
										 |  |  | #include "Common/CommonTypes.h"
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | #include "Common/Logging/Log.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "Common/MathUtil.h"
 | 
					
						
							| 
									
										
										
										
											2015-09-26 17:13:07 -04:00
										 |  |  | #include "Common/MsgHandler.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "Common/StringUtil.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-21 01:47:53 +01:00
										 |  |  | #include "DiscIO/Blob.h"
 | 
					
						
							|  |  |  | #include "DiscIO/Volume.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "DiscIO/VolumeWad.h"
 | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | #define ALIGN_40(x) ROUND_UP(Common::swap32(x), 0x40)
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace DiscIO | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2015-08-31 19:27:18 -04:00
										 |  |  | CVolumeWAD::CVolumeWAD(std::unique_ptr<IBlobReader> reader) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     : m_pReader(std::move(reader)), m_offset(0), m_tmd_offset(0), m_opening_bnr_offset(0), | 
					
						
							|  |  |  |       m_hdr_size(0), m_cert_size(0), m_tick_size(0), m_tmd_size(0), m_data_size(0) | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   // Source: http://wiibrew.org/wiki/WAD_files
 | 
					
						
							|  |  |  |   Read(0x00, 4, (u8*)&m_hdr_size); | 
					
						
							|  |  |  |   Read(0x08, 4, (u8*)&m_cert_size); | 
					
						
							|  |  |  |   Read(0x10, 4, (u8*)&m_tick_size); | 
					
						
							|  |  |  |   Read(0x14, 4, (u8*)&m_tmd_size); | 
					
						
							|  |  |  |   Read(0x18, 4, (u8*)&m_data_size); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   m_offset = ALIGN_40(m_hdr_size) + ALIGN_40(m_cert_size); | 
					
						
							|  |  |  |   m_tmd_offset = ALIGN_40(m_hdr_size) + ALIGN_40(m_cert_size) + ALIGN_40(m_tick_size); | 
					
						
							|  |  |  |   m_opening_bnr_offset = m_tmd_offset + ALIGN_40(m_tmd_size) + ALIGN_40(m_data_size); | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CVolumeWAD::~CVolumeWAD() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2014-12-28 10:35:48 +01:00
										 |  |  | bool CVolumeWAD::Read(u64 _Offset, u64 _Length, u8* _pBuffer, bool decrypt) const | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (decrypt) | 
					
						
							|  |  |  |     PanicAlertT("Tried to decrypt data from a non-Wii volume"); | 
					
						
							| 
									
										
										
										
											2014-12-28 10:35:48 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (m_pReader == nullptr) | 
					
						
							|  |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return m_pReader->Read(_Offset, _Length, _pBuffer); | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IVolume::ECountry CVolumeWAD::GetCountry() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (!m_pReader) | 
					
						
							|  |  |  |     return COUNTRY_UNKNOWN; | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   // read the last digit of the titleID in the ticket
 | 
					
						
							|  |  |  |   u8 country_code; | 
					
						
							|  |  |  |   Read(m_tmd_offset + 0x0193, 1, &country_code); | 
					
						
							| 
									
										
										
										
											2015-02-23 19:50:19 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (country_code == 2)  // SYSMENU
 | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     u16 title_version = 0; | 
					
						
							|  |  |  |     Read(m_tmd_offset + 0x01dc, 2, (u8*)&title_version); | 
					
						
							|  |  |  |     country_code = GetSysMenuRegion(Common::swap16(title_version)); | 
					
						
							|  |  |  |   } | 
					
						
							| 
									
										
										
										
											2015-02-23 19:50:19 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return CountrySwitch(country_code); | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::string CVolumeWAD::GetUniqueID() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   char GameCode[6]; | 
					
						
							|  |  |  |   if (!Read(m_offset + 0x01E0, 4, (u8*)GameCode)) | 
					
						
							|  |  |  |     return "0"; | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   std::string temp = GetMakerID(); | 
					
						
							|  |  |  |   GameCode[4] = temp.at(0); | 
					
						
							|  |  |  |   GameCode[5] = temp.at(1); | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return DecodeString(GameCode); | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::string CVolumeWAD::GetMakerID() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   char temp[2] = {1}; | 
					
						
							| 
									
										
										
										
											2016-06-25 18:07:10 +02:00
										 |  |  |   // Some weird channels use 0x0000 in place of the MakerID, so we need a check there
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (!Read(0x198 + m_tmd_offset, 2, (u8*)temp) || temp[0] == 0 || temp[1] == 0) | 
					
						
							|  |  |  |     return "00"; | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return DecodeString(temp); | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-22 13:25:54 -04:00
										 |  |  | bool CVolumeWAD::GetTitleID(u64* buffer) const | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (!Read(m_offset + 0x01DC, sizeof(u64), reinterpret_cast<u8*>(buffer))) | 
					
						
							|  |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   *buffer = Common::swap64(*buffer); | 
					
						
							|  |  |  |   return true; | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-05-29 21:14:02 +02:00
										 |  |  | u16 CVolumeWAD::GetRevision() const | 
					
						
							| 
									
										
										
										
											2015-01-30 20:43:48 -05:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   u16 revision; | 
					
						
							|  |  |  |   if (!m_pReader->Read(m_tmd_offset + 0x1dc, 2, (u8*)&revision)) | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2015-01-30 20:43:48 -05:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return Common::swap16(revision); | 
					
						
							| 
									
										
										
										
											2015-01-30 20:43:48 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-06-04 16:26:36 +02:00
										 |  |  | IVolume::EPlatform CVolumeWAD::GetVolumeType() const | 
					
						
							| 
									
										
										
										
											2015-01-17 13:21:02 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return WII_WAD; | 
					
						
							| 
									
										
										
										
											2015-01-17 13:21:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-02-29 19:52:15 +11:00
										 |  |  | std::map<IVolume::ELanguage, std::string> CVolumeWAD::GetLongNames() const | 
					
						
							| 
									
										
										
										
											2011-12-18 21:42:20 -08:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   std::vector<u8> name_data(NAMES_TOTAL_BYTES); | 
					
						
							|  |  |  |   if (!Read(m_opening_bnr_offset + 0x9C, NAMES_TOTAL_BYTES, name_data.data())) | 
					
						
							|  |  |  |     return std::map<IVolume::ELanguage, std::string>(); | 
					
						
							|  |  |  |   return ReadWiiNames(name_data); | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-12-03 17:29:59 +01:00
										 |  |  | std::vector<u32> CVolumeWAD::GetBanner(int* width, int* height) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   *width = 0; | 
					
						
							|  |  |  |   *height = 0; | 
					
						
							| 
									
										
										
										
											2015-12-03 17:29:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   u64 title_id; | 
					
						
							|  |  |  |   if (!GetTitleID(&title_id)) | 
					
						
							|  |  |  |     return std::vector<u32>(); | 
					
						
							| 
									
										
										
										
											2015-12-03 17:29:59 +01:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return GetWiiBanner(width, height, title_id); | 
					
						
							| 
									
										
										
										
											2015-12-03 17:29:59 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2015-09-27 14:01:12 +02:00
										 |  |  | BlobType CVolumeWAD::GetBlobType() const | 
					
						
							| 
									
										
										
										
											2015-09-26 15:24:29 +02:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   return m_pReader ? m_pReader->GetBlobType() : BlobType::PLAIN; | 
					
						
							| 
									
										
										
										
											2015-09-26 15:24:29 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | u64 CVolumeWAD::GetSize() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (m_pReader) | 
					
						
							|  |  |  |     return m_pReader->GetDataSize(); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2013-04-09 12:58:56 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | u64 CVolumeWAD::GetRawSize() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   if (m_pReader) | 
					
						
							|  |  |  |     return m_pReader->GetRawSize(); | 
					
						
							|  |  |  |   else | 
					
						
							|  |  |  |     return 0; | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | }  // namespace
 |