| 
									
										
										
										
											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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-11-27 11:56:22 +01:00
										 |  |  | #include "Common/Align.h"
 | 
					
						
							| 
									
										
										
										
											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"
 | 
					
						
							| 
									
										
										
										
											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"
 | 
					
						
							| 
									
										
										
										
											2016-07-06 20:33:05 +02:00
										 |  |  | #include "DiscIO/Enums.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-21 01:47:53 +01:00
										 |  |  | #include "DiscIO/Volume.h"
 | 
					
						
							| 
									
										
										
										
											2014-02-17 05:18:15 -05:00
										 |  |  | #include "DiscIO/VolumeWad.h"
 | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | namespace DiscIO | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-01-23 18:06:08 +01:00
										 |  |  | CVolumeWAD::CVolumeWAD(std::unique_ptr<IBlobReader> reader) : m_reader(std::move(reader)) | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   // Source: http://wiibrew.org/wiki/WAD_files
 | 
					
						
							| 
									
										
										
										
											2017-01-23 18:33:49 +01:00
										 |  |  |   ReadSwapped(0x00, &m_hdr_size, false); | 
					
						
							|  |  |  |   ReadSwapped(0x08, &m_cert_size, false); | 
					
						
							|  |  |  |   ReadSwapped(0x10, &m_tick_size, false); | 
					
						
							|  |  |  |   ReadSwapped(0x14, &m_tmd_size, false); | 
					
						
							|  |  |  |   ReadSwapped(0x18, &m_data_size, false); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   m_offset = Common::AlignUp(m_hdr_size, 0x40) + Common::AlignUp(m_cert_size, 0x40); | 
					
						
							|  |  |  |   m_tmd_offset = Common::AlignUp(m_hdr_size, 0x40) + Common::AlignUp(m_cert_size, 0x40) + | 
					
						
							|  |  |  |                  Common::AlignUp(m_tick_size, 0x40); | 
					
						
							|  |  |  |   m_opening_bnr_offset = | 
					
						
							|  |  |  |       m_tmd_offset + Common::AlignUp(m_tmd_size, 0x40) + Common::AlignUp(m_data_size, 0x40); | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CVolumeWAD::~CVolumeWAD() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-23 18:06:08 +01:00
										 |  |  | bool CVolumeWAD::Read(u64 offset, u64 length, u8* buffer, 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
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-23 18:06:08 +01:00
										 |  |  |   if (m_reader == nullptr) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     return false; | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-23 18:06:08 +01:00
										 |  |  |   return m_reader->Read(offset, length, buffer); | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-23 18:41:21 +01:00
										 |  |  | Region CVolumeWAD::GetRegion() const | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-12-23 18:41:21 +01:00
										 |  |  |   u8 country_code; | 
					
						
							|  |  |  |   if (!Read(m_tmd_offset + 0x0193, 1, &country_code)) | 
					
						
							|  |  |  |     return Region::UNKNOWN_REGION; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |   return RegionSwitchWii(country_code); | 
					
						
							|  |  |  | } | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-12-23 18:41:21 +01:00
										 |  |  | Country CVolumeWAD::GetCountry() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   // read the last digit of the titleID in the ticket
 | 
					
						
							|  |  |  |   u8 country_code; | 
					
						
							| 
									
										
										
										
											2016-12-23 18:41:21 +01:00
										 |  |  |   if (!Read(m_tmd_offset + 0x0193, 1, &country_code)) | 
					
						
							|  |  |  |     return Country::COUNTRY_UNKNOWN; | 
					
						
							| 
									
										
										
										
											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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2017-01-23 18:33:49 +01:00
										 |  |  | std::vector<u8> CVolumeWAD::GetTMD() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  |   if (m_tmd_size > 1024 * 1024 * 4) | 
					
						
							|  |  |  |   { | 
					
						
							|  |  |  |     ERROR_LOG(DISCIO, "TMD is too large: %u bytes", m_tmd_size); | 
					
						
							|  |  |  |     return {}; | 
					
						
							|  |  |  |   } | 
					
						
							|  |  |  |   std::vector<u8> buffer(m_tmd_size); | 
					
						
							|  |  |  |   Read(m_tmd_offset, m_tmd_size, buffer.data(), false); | 
					
						
							|  |  |  |   return buffer; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-10-29 14:42:43 +02:00
										 |  |  | std::string CVolumeWAD::GetGameID() const | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											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; | 
					
						
							| 
									
										
										
										
											2017-01-23 18:06:08 +01:00
										 |  |  |   if (!m_reader->Read(m_tmd_offset + 0x1dc, 2, (u8*)&revision)) | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |     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
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-06 20:33:05 +02:00
										 |  |  | Platform CVolumeWAD::GetVolumeType() const | 
					
						
							| 
									
										
										
										
											2015-01-17 13:21:02 +01:00
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2016-07-06 20:33:05 +02:00
										 |  |  |   return Platform::WII_WAD; | 
					
						
							| 
									
										
										
										
											2015-01-17 13:21:02 +01:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-07-06 20:33:05 +02:00
										 |  |  | std::map<Language, 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())) | 
					
						
							| 
									
										
										
										
											2016-07-06 20:33:05 +02:00
										 |  |  |     return std::map<Language, std::string>(); | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  |   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
										 |  |  | { | 
					
						
							| 
									
										
										
										
											2017-01-23 18:06:08 +01:00
										 |  |  |   return m_reader ? m_reader->GetBlobType() : BlobType::PLAIN; | 
					
						
							| 
									
										
										
										
											2015-09-26 15:24:29 +02:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | u64 CVolumeWAD::GetSize() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-01-23 18:09:29 +01:00
										 |  |  |   return m_reader ? m_reader->GetDataSize() : 0; | 
					
						
							| 
									
										
										
										
											2013-04-09 12:58:56 -05:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | u64 CVolumeWAD::GetRawSize() const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2017-01-23 18:09:29 +01:00
										 |  |  |   return m_reader ? m_reader->GetRawSize() : 0; | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2016-06-24 10:43:46 +02:00
										 |  |  | }  // namespace
 |