| 
									
										
										
										
											2009-07-28 21:32:10 +00:00
										 |  |  | // Copyright (C) 2003 Dolphin Project.
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | // This program is free software: you can redistribute it and/or modify
 | 
					
						
							|  |  |  | // it under the terms of the GNU General Public License as published by
 | 
					
						
							|  |  |  | // the Free Software Foundation, version 2.0.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // This program is distributed in the hope that it will be useful,
 | 
					
						
							|  |  |  | // but WITHOUT ANY WARRANTY; without even the implied warranty of
 | 
					
						
							|  |  |  | // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 | 
					
						
							|  |  |  | // GNU General Public License 2.0 for more details.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // A copy of the GPL 2.0 should have been included with the program.
 | 
					
						
							|  |  |  | // If not, see http://www.gnu.org/licenses/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // Official SVN repository and contact information can be found at
 | 
					
						
							|  |  |  | // http://code.google.com/p/dolphin-emu/
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2010-07-20 03:23:25 +00:00
										 |  |  | #include "Common.h"
 | 
					
						
							|  |  |  | #include "CommonPaths.h"
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | #include "VolumeDirectory.h"
 | 
					
						
							|  |  |  | #include "FileBlob.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace DiscIO | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static const u8 ENTRY_SIZE = 0x0c; | 
					
						
							|  |  |  | static const u8 FILE_ENTRY = 0; | 
					
						
							|  |  |  | static const u8 DIRECTORY_ENTRY = 1; | 
					
						
							| 
									
										
										
										
											2009-12-10 09:16:10 +00:00
										 |  |  | static const u64 DISKHEADER_ADDRESS = 0; | 
					
						
							|  |  |  | static const u64 DISKHEADERINFO_ADDRESS = 0x440; | 
					
						
							|  |  |  | static const u64 APPLOADER_ADDRESS = 0x2440; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | static const u32 MAX_NAME_LENGTH = 0x3df; | 
					
						
							| 
									
										
										
										
											2009-12-10 09:16:10 +00:00
										 |  |  | // relocatable
 | 
					
						
							|  |  |  | static u64 FST_ADDRESS = 0x440; | 
					
						
							|  |  |  | static u64 DOL_ADDRESS = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-14 05:27:29 +00:00
										 |  |  | CVolumeDirectory::CVolumeDirectory(const std::string& _rDirectory, bool _bIsWii, | 
					
						
							|  |  |  | 								   const std::string& _rApploader, const std::string& _rDOL) | 
					
						
							| 
									
										
										
										
											2010-01-29 19:45:01 +00:00
										 |  |  | 	: m_totalNameSize(0) | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	, m_dataStartAddress(-1) | 
					
						
							|  |  |  | 	, m_fstSize(0) | 
					
						
							|  |  |  | 	, m_FSTData(NULL) | 
					
						
							| 
									
										
										
										
											2010-01-29 19:45:01 +00:00
										 |  |  | 	, m_apploaderSize(0) | 
					
						
							|  |  |  | 	, m_apploader(NULL) | 
					
						
							|  |  |  | 	, m_DOLSize(0) | 
					
						
							|  |  |  | 	, m_DOL(NULL) | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | { | 
					
						
							|  |  |  | 	m_rootDirectory = ExtractDirectoryName(_rDirectory);	 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// create the default disk header
 | 
					
						
							| 
									
										
										
										
											2009-12-14 05:27:29 +00:00
										 |  |  | 	m_diskHeader = new u8[DISKHEADERINFO_ADDRESS]; | 
					
						
							|  |  |  | 	memset(m_diskHeader, 0, (size_t)DISKHEADERINFO_ADDRESS); | 
					
						
							| 
									
										
										
										
											2010-02-08 22:22:20 +00:00
										 |  |  | 	SetUniqueID("AGBJ01");	 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	SetName("Default name"); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(_bIsWii) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		SetDiskTypeWii(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		SetDiskTypeGC(); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-10 09:16:10 +00:00
										 |  |  | 	m_diskHeaderInfo = new SDiskHeaderInfo(); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Don't load the dol if we've no apploader...
 | 
					
						
							|  |  |  | 	if (SetApploader(_rApploader)) | 
					
						
							|  |  |  | 		SetDOL(_rDOL); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	BuildFST(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CVolumeDirectory::~CVolumeDirectory() | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-10 09:16:10 +00:00
										 |  |  | 	delete[] m_FSTData; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	m_FSTData = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-10 09:16:10 +00:00
										 |  |  | 	delete[] m_diskHeader; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	m_diskHeader = NULL; | 
					
						
							| 
									
										
										
										
											2009-12-10 09:16:10 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	delete m_diskHeaderInfo; | 
					
						
							|  |  |  | 	m_diskHeaderInfo = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	delete[] m_DOL; | 
					
						
							|  |  |  | 	m_DOL = NULL; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	delete[] m_apploader; | 
					
						
							|  |  |  | 	m_apploader = NULL; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool CVolumeDirectory::IsValidDirectory(const std::string& _rDirectory) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	std::string directoryName = ExtractDirectoryName(_rDirectory); | 
					
						
							| 
									
										
										
										
											2011-03-01 03:06:14 +00:00
										 |  |  | 	return File::IsDirectory(directoryName); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-02-22 13:59:06 +00:00
										 |  |  | bool CVolumeDirectory::RAWRead( u64 _Offset, u64 _Length, u8* _pBuffer ) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return false; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | bool CVolumeDirectory::Read(u64 _Offset, u64 _Length, u8* _pBuffer) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-12-10 09:16:10 +00:00
										 |  |  | 	// header
 | 
					
						
							|  |  |  | 	if(_Offset < DISKHEADERINFO_ADDRESS) | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-10 09:16:10 +00:00
										 |  |  | 		WriteToBuffer(DISKHEADER_ADDRESS, DISKHEADERINFO_ADDRESS, m_diskHeader, _Offset, _Length, _pBuffer); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	} | 
					
						
							| 
									
										
										
										
											2009-12-10 09:16:10 +00:00
										 |  |  | 	// header info
 | 
					
						
							| 
									
										
										
										
											2009-12-14 05:27:29 +00:00
										 |  |  | 	if(_Offset >= DISKHEADERINFO_ADDRESS && _Offset < APPLOADER_ADDRESS) | 
					
						
							| 
									
										
										
										
											2009-12-10 09:16:10 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		WriteToBuffer(DISKHEADERINFO_ADDRESS, sizeof(m_diskHeaderInfo), (u8*)m_diskHeaderInfo, _Offset, _Length, _pBuffer); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// apploader
 | 
					
						
							| 
									
										
										
										
											2009-12-14 05:27:29 +00:00
										 |  |  | 	if(_Offset >= APPLOADER_ADDRESS && _Offset < APPLOADER_ADDRESS + m_apploaderSize) | 
					
						
							| 
									
										
										
										
											2009-12-10 09:16:10 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		WriteToBuffer(APPLOADER_ADDRESS, m_apploaderSize, m_apploader, _Offset, _Length, _pBuffer); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// dol
 | 
					
						
							| 
									
										
										
										
											2009-12-14 05:27:29 +00:00
										 |  |  | 	if(_Offset >= DOL_ADDRESS && _Offset < DOL_ADDRESS + m_DOLSize) | 
					
						
							| 
									
										
										
										
											2009-12-10 09:16:10 +00:00
										 |  |  | 	{ | 
					
						
							|  |  |  | 		WriteToBuffer(DOL_ADDRESS, m_DOLSize, m_DOL, _Offset, _Length, _pBuffer); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	// fst
 | 
					
						
							| 
									
										
										
										
											2009-12-14 05:27:29 +00:00
										 |  |  | 	if(_Offset >= FST_ADDRESS && _Offset < m_dataStartAddress) | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	{ | 
					
						
							| 
									
										
										
										
											2009-12-10 09:16:10 +00:00
										 |  |  | 		WriteToBuffer(FST_ADDRESS, m_fstSize, m_FSTData, _Offset, _Length, _pBuffer); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	if(m_virtualDisk.size() == 0) | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// Determine which file the offset refers to
 | 
					
						
							|  |  |  | 	std::map<u64, std::string>::const_iterator fileIter = m_virtualDisk.lower_bound(_Offset); | 
					
						
							|  |  |  | 	if(fileIter->first > _Offset && fileIter != m_virtualDisk.begin()) | 
					
						
							|  |  |  | 		--fileIter; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// zero fill to start of file data
 | 
					
						
							|  |  |  | 	PadToAddress(fileIter->first, _Offset, _Length, _pBuffer); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	while(fileIter != m_virtualDisk.end() && _Length > 0) | 
					
						
							|  |  |  | 	{	 | 
					
						
							|  |  |  | 		_dbg_assert_(DVDINTERFACE, fileIter->first <= _Offset); | 
					
						
							|  |  |  | 		u64 fileOffset = _Offset - fileIter->first; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		PlainFileReader* reader = PlainFileReader::Create(fileIter->second.c_str());		 | 
					
						
							|  |  |  | 		if(reader == NULL) | 
					
						
							|  |  |  | 			return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		u64 fileSize = reader->GetDataSize(); | 
					
						
							|  |  |  | 		 | 
					
						
							|  |  |  | 		if(fileOffset < fileSize) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			u64 fileBytes = fileSize - fileOffset; | 
					
						
							|  |  |  | 			if(_Length < fileBytes) | 
					
						
							|  |  |  | 				fileBytes = _Length; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			if(!reader->Read(fileOffset, fileBytes, _pBuffer)) | 
					
						
							|  |  |  | 				return false; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 			_Length -= fileBytes; | 
					
						
							|  |  |  | 			_pBuffer += fileBytes; | 
					
						
							|  |  |  | 			_Offset += fileBytes; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		++fileIter; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if(fileIter != m_virtualDisk.end()) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			_dbg_assert_(DVDINTERFACE, fileIter->first >= _Offset); | 
					
						
							|  |  |  | 			PadToAddress(fileIter->first, _Offset, _Length, _pBuffer); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2010-02-08 22:22:20 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		delete reader; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	return true; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::string CVolumeDirectory::GetUniqueID() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	_dbg_assert_(DVDINTERFACE, m_diskHeader); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	char buffer[7]; | 
					
						
							|  |  |  | 	memcpy(buffer, m_diskHeader, 6); | 
					
						
							|  |  |  | 	buffer[6] = 0; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	std::string id = buffer; | 
					
						
							|  |  |  | 	return id; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CVolumeDirectory::SetUniqueID(std::string _ID) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	_dbg_assert_(DVDINTERFACE, m_diskHeader); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-24 00:45:46 +00:00
										 |  |  | 	u32 length = (u32)_ID.length(); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	if(length > 6) | 
					
						
							|  |  |  | 		length = 6; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memcpy(m_diskHeader, _ID.c_str(), length); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IVolume::ECountry CVolumeDirectory::GetCountry() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	_dbg_assert_(DVDINTERFACE, m_diskHeader); | 
					
						
							|  |  |  | 	 | 
					
						
							|  |  |  | 	u8 CountryCode = m_diskHeader[3]; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | 	return CountrySwitch(CountryCode); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::string CVolumeDirectory::GetMakerID() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return "VOID"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::string CVolumeDirectory::GetName() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	_dbg_assert_(DVDINTERFACE, m_diskHeader); | 
					
						
							|  |  |  | 	std::string name = (char*)(m_diskHeader + 0x20); | 
					
						
							|  |  |  | 	return name; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CVolumeDirectory::SetName(std::string _Name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	_dbg_assert_(DVDINTERFACE, m_diskHeader); | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-01-24 00:45:46 +00:00
										 |  |  | 	u32 length = (u32)_Name.length(); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	if(length > MAX_NAME_LENGTH) | 
					
						
							|  |  |  | 		length = MAX_NAME_LENGTH; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memcpy(m_diskHeader + 0x20, _Name.c_str(), length); | 
					
						
							|  |  |  | 	m_diskHeader[length + 0x20] = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | u32 CVolumeDirectory::GetFSTSize() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::string CVolumeDirectory::GetApploaderDate() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return "VOID"; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | u64 CVolumeDirectory::GetSize() const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | std::string CVolumeDirectory::ExtractDirectoryName(const std::string& _rDirectory) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	std::string directoryName = _rDirectory; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-07-03 22:34:51 +00:00
										 |  |  | 	size_t lastSep = directoryName.find_last_of(DIR_SEP_CHR); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	if(lastSep != directoryName.size() - 1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		// TODO: This assumes that file names will always have a dot in them
 | 
					
						
							| 
									
										
										
										
											2009-03-07 18:03:53 +00:00
										 |  |  | 		//	   and directory names never will; both assumptions are often
 | 
					
						
							|  |  |  | 		//	   right but in general wrong.
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 		size_t extensionStart = directoryName.find_last_of('.'); | 
					
						
							|  |  |  | 		if(extensionStart != std::string::npos && extensionStart > lastSep) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			directoryName.resize(lastSep); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		directoryName.resize(lastSep); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return directoryName; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CVolumeDirectory::SetDiskTypeWii() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	_dbg_assert_(DVDINTERFACE, m_diskHeader); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_diskHeader[0x18] = 0x5d; | 
					
						
							|  |  |  | 	m_diskHeader[0x19] = 0x1c; | 
					
						
							|  |  |  | 	m_diskHeader[0x1a] = 0x9e; | 
					
						
							|  |  |  | 	m_diskHeader[0x1b] = 0xa3;	 | 
					
						
							|  |  |  | 	memset(m_diskHeader + 0x1c, 0, 4); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_addressShift = 2; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CVolumeDirectory::SetDiskTypeGC() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	_dbg_assert_(DVDINTERFACE, m_diskHeader); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	memset(m_diskHeader + 0x18, 0, 4); | 
					
						
							|  |  |  | 	m_diskHeader[0x1c] = 0xc2; | 
					
						
							|  |  |  | 	m_diskHeader[0x1d] = 0x33; | 
					
						
							|  |  |  | 	m_diskHeader[0x1e] = 0x9f; | 
					
						
							|  |  |  | 	m_diskHeader[0x1f] = 0x3d; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_addressShift = 0; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2009-12-10 09:16:10 +00:00
										 |  |  | bool CVolumeDirectory::SetApploader(const std::string& _rApploader) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!_rApploader.empty()) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		std::string data; | 
					
						
							| 
									
										
										
										
											2009-12-14 05:27:29 +00:00
										 |  |  | 		if (!File::ReadFileToString(false, _rApploader.c_str(), data)) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2011-01-13 02:05:58 +00:00
										 |  |  | 			PanicAlertT("Apploader unable to load from file"); | 
					
						
							| 
									
										
										
										
											2009-12-14 05:27:29 +00:00
										 |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-12-10 09:16:10 +00:00
										 |  |  | 		m_apploaderSize = 0x20 + Common::swap32(*(u32*)&data.data()[0x14]) + Common::swap32(*(u32*)&data.data()[0x18]); | 
					
						
							|  |  |  | 		if (m_apploaderSize != data.size()) | 
					
						
							|  |  |  | 		{ | 
					
						
							| 
									
										
										
										
											2011-01-13 02:05:58 +00:00
										 |  |  | 			PanicAlertT("Apploader is the wrong size...is it really an apploader?"); | 
					
						
							| 
									
										
										
										
											2009-12-10 09:16:10 +00:00
										 |  |  | 			return false; | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		m_apploader = new u8[m_apploaderSize]; | 
					
						
							|  |  |  | 		copy(data.begin(), data.end(), m_apploader); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// 32byte aligned (plus 0x20 padding)
 | 
					
						
							|  |  |  | 		DOL_ADDRESS = (APPLOADER_ADDRESS + m_apploaderSize + 0x20 + 31) & ~31ULL; | 
					
						
							|  |  |  | 		return true; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		m_apploaderSize = 0x20; | 
					
						
							|  |  |  | 		m_apploader = new u8[m_apploaderSize]; | 
					
						
							|  |  |  | 		// Make sure BS2 HLE doesn't try to run the apploader
 | 
					
						
							|  |  |  | 		*(u32*)&m_apploader[0x10] = (u32)-1; | 
					
						
							|  |  |  | 		return false; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CVolumeDirectory::SetDOL(const std::string& _rDOL) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (!_rDOL.empty()) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		std::string data; | 
					
						
							|  |  |  | 		File::ReadFileToString(false, _rDOL.c_str(), data); | 
					
						
							|  |  |  | 		m_DOLSize = data.size(); | 
					
						
							|  |  |  | 		m_DOL = new u8[m_DOLSize]; | 
					
						
							|  |  |  | 		copy(data.begin(), data.end(), m_DOL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		Write32((u32)(DOL_ADDRESS >> m_addressShift), 0x0420, m_diskHeader); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// 32byte aligned (plus 0x20 padding)
 | 
					
						
							|  |  |  | 		FST_ADDRESS = (DOL_ADDRESS + m_DOLSize + 0x20 + 31) & ~31ULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | void CVolumeDirectory::BuildFST() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(m_FSTData) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		delete m_FSTData; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	File::FSTEntry rootEntry; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// read data from physical disk to rootEntry
 | 
					
						
							|  |  |  | 	u32 totalEntries = AddDirectoryEntries(m_rootDirectory, rootEntry) + 1; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_fstNameOffset = totalEntries * ENTRY_SIZE;	// offset in FST nameTable
 | 
					
						
							|  |  |  | 	m_fstSize = m_fstNameOffset + m_totalNameSize; | 
					
						
							|  |  |  | 	m_FSTData = new u8[(u32)m_fstSize]; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// 4 byte aligned start of data on disk
 | 
					
						
							|  |  |  | 	m_dataStartAddress = (FST_ADDRESS + m_fstSize + 3) & ~3; | 
					
						
							|  |  |  | 	u64 curDataAddress = m_dataStartAddress; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	u32 fstOffset = 0;		// offset within FST data
 | 
					
						
							|  |  |  | 	u32 nameOffset = 0;		// offset within name table
 | 
					
						
							|  |  |  | 	u32 rootOffset = 0;		// offset of root of FST
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// write root entry
 | 
					
						
							|  |  |  | 	WriteEntryData(fstOffset, DIRECTORY_ENTRY, 0, 0, totalEntries); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	for(std::vector<File::FSTEntry>::iterator iter = rootEntry.children.begin(); iter != rootEntry.children.end(); ++iter) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		WriteEntry(*iter, fstOffset, nameOffset, curDataAddress, rootOffset); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	// overflow check
 | 
					
						
							| 
									
										
										
										
											2009-01-11 22:25:57 +00:00
										 |  |  | 	_dbg_assert_(DVDINTERFACE, nameOffset == m_totalNameSize); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 	// write FST size and location
 | 
					
						
							|  |  |  | 	_dbg_assert_(DVDINTERFACE, m_diskHeader); | 
					
						
							|  |  |  | 	Write32((u32)(FST_ADDRESS >> m_addressShift), 0x0424, m_diskHeader); | 
					
						
							|  |  |  | 	Write32((u32)m_fstSize, 0x0428, m_diskHeader); | 
					
						
							|  |  |  | 	Write32((u32)m_fstSize, 0x042c, m_diskHeader); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CVolumeDirectory::WriteToBuffer(u64 _SrcStartAddress, u64 _SrcLength, u8* _Src, | 
					
						
							|  |  |  | 									 u64& _Address, u64& _Length, u8*& _pBuffer) const | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2009-01-11 22:25:57 +00:00
										 |  |  | 	if(_Length == 0) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	_dbg_assert_(DVDINTERFACE, _Address >= _SrcStartAddress); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	u64 srcOffset = _Address - _SrcStartAddress; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(srcOffset < _SrcLength) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		u64 srcBytes = _SrcLength - srcOffset; | 
					
						
							|  |  |  | 		if(_Length < srcBytes) | 
					
						
							|  |  |  | 			srcBytes = _Length; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		memcpy(_pBuffer, _Src + srcOffset, (size_t)srcBytes); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		_Length -= srcBytes; | 
					
						
							|  |  |  | 		_pBuffer += srcBytes; | 
					
						
							|  |  |  | 		_Address += srcBytes; | 
					
						
							|  |  |  | 	}	 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CVolumeDirectory::PadToAddress(u64 _StartAddress, u64& _Address, u64& _Length, u8*& _pBuffer) const | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if(_StartAddress <= _Address) | 
					
						
							|  |  |  | 		return; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	u64 padBytes = _StartAddress - _Address; | 
					
						
							|  |  |  | 	if(padBytes > _Length) | 
					
						
							|  |  |  | 		padBytes = _Length; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if(_Length > 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		memset(_pBuffer, 0, (size_t)padBytes); | 
					
						
							|  |  |  | 		_Length -= padBytes; | 
					
						
							|  |  |  | 		_pBuffer += padBytes; | 
					
						
							|  |  |  | 		_Address += padBytes; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CVolumeDirectory::Write32(u32 data, u32 offset, u8* buffer) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	buffer[offset++] = (data >> 24); | 
					
						
							|  |  |  | 	buffer[offset++] = (data >> 16) & 0xff; | 
					
						
							|  |  |  | 	buffer[offset++] = (data >> 8) & 0xff; | 
					
						
							|  |  |  | 	buffer[offset] = (data) & 0xff; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CVolumeDirectory::WriteEntryData(u32& entryOffset, u8 type, u32 nameOffset, u64 dataOffset, u32 length) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	m_FSTData[entryOffset++] = type; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	m_FSTData[entryOffset++] = (nameOffset >> 16) & 0xff; | 
					
						
							|  |  |  | 	m_FSTData[entryOffset++] = (nameOffset >> 8) & 0xff; | 
					
						
							|  |  |  | 	m_FSTData[entryOffset++] = (nameOffset) & 0xff; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Write32((u32)(dataOffset >> m_addressShift), entryOffset, m_FSTData); | 
					
						
							|  |  |  | 	entryOffset += 4; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	Write32((u32)length, entryOffset, m_FSTData); | 
					
						
							|  |  |  | 	entryOffset += 4; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CVolumeDirectory::WriteEntryName(u32& nameOffset, const std::string& name) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	strncpy((char*)(m_FSTData + nameOffset + m_fstNameOffset), name.c_str(), name.length() + 1); | 
					
						
							|  |  |  | 	 | 
					
						
							| 
									
										
										
										
											2009-01-24 00:45:46 +00:00
										 |  |  | 	nameOffset += (u32)(name.length() + 1); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CVolumeDirectory::WriteEntry(const File::FSTEntry& entry, u32& fstOffset, u32& nameOffset, u64& dataOffset, u32 parentEntryNum) | 
					
						
							|  |  |  | {	 | 
					
						
							|  |  |  | 	if(entry.isDirectory) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		u32 myOffset = fstOffset; | 
					
						
							|  |  |  | 		u32 myEntryNum = myOffset / ENTRY_SIZE;		 | 
					
						
							| 
									
										
										
										
											2009-02-28 01:26:56 +00:00
										 |  |  | 		WriteEntryData(fstOffset, DIRECTORY_ENTRY, nameOffset, parentEntryNum, (u32)(myEntryNum + entry.size + 1)); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 		WriteEntryName(nameOffset, entry.virtualName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		for(std::vector<File::FSTEntry>::const_iterator iter = entry.children.begin(); iter != entry.children.end(); ++iter) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			WriteEntry(*iter, fstOffset, nameOffset, dataOffset, myEntryNum); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		// put entry in FST
 | 
					
						
							| 
									
										
										
										
											2009-02-28 01:26:56 +00:00
										 |  |  | 		WriteEntryData(fstOffset, FILE_ENTRY, nameOffset, dataOffset, (u32)entry.size); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 		WriteEntryName(nameOffset, entry.virtualName); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// write entry to virtual disk
 | 
					
						
							|  |  |  | 		_dbg_assert_(DVDINTERFACE, m_virtualDisk.find(dataOffset) == m_virtualDisk.end()); | 
					
						
							|  |  |  | 		m_virtualDisk.insert(make_pair(dataOffset, entry.physicalName)); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		// 4 byte aligned
 | 
					
						
							|  |  |  | 		dataOffset = (dataOffset + entry.size + 3) & ~3ULL; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | static u32 ComputeNameSize(const File::FSTEntry& parentEntry) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	u32 nameSize = 0; | 
					
						
							|  |  |  | 	const std::vector<File::FSTEntry>& children = parentEntry.children; | 
					
						
							|  |  |  | 	for (std::vector<File::FSTEntry>::const_iterator it = children.begin(); | 
					
						
							|  |  |  | 		it != children.end(); ++it) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		const File::FSTEntry& entry = *it; | 
					
						
							|  |  |  | 		if (entry.isDirectory) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			nameSize += ComputeNameSize(entry); | 
					
						
							|  |  |  | 		} | 
					
						
							| 
									
										
										
										
											2009-01-24 00:45:46 +00:00
										 |  |  | 		nameSize += (u32)entry.virtualName.length() + 1; | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	} | 
					
						
							|  |  |  | 	return nameSize; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | u32 CVolumeDirectory::AddDirectoryEntries(const std::string& _Directory, File::FSTEntry& parentEntry) | 
					
						
							|  |  |  | { | 
					
						
							| 
									
										
										
										
											2011-03-01 03:06:14 +00:00
										 |  |  | 	u32 foundEntries = ScanDirectoryTree(_Directory, parentEntry); | 
					
						
							| 
									
										
										
										
											2008-12-08 05:30:24 +00:00
										 |  |  | 	m_totalNameSize += ComputeNameSize(parentEntry); | 
					
						
							|  |  |  | 	return foundEntries; | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } // namespace
 |