| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | // Copyright (C) 2003-2008 Dolphin Project.
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | // 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/
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  | #include <windows.h>
 | 
					
						
							| 
									
										
										
										
											2008-07-30 09:12:52 +00:00
										 |  |  | #else
 | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | #include <unistd.h>
 | 
					
						
							|  |  |  | #include <sys/mman.h>
 | 
					
						
							|  |  |  | #include <sys/stat.h>
 | 
					
						
							|  |  |  | #include <fcntl.h>
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #include "Common.h"
 | 
					
						
							|  |  |  | #include "MappedFile.h"
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | namespace Common | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | class CMappedFile | 
					
						
							|  |  |  | 	: public IMappedFile | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	public: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		CMappedFile(void); | 
					
						
							|  |  |  | 		~CMappedFile(void); | 
					
						
							|  |  |  | 		bool Open(const char* _szFilename); | 
					
						
							|  |  |  | 		bool IsOpen(void); | 
					
						
							|  |  |  | 		void Close(void); | 
					
						
							|  |  |  | 		u64 GetSize(void); | 
					
						
							|  |  |  | 		u8* Lock(u64 _offset, u64 _size); | 
					
						
							|  |  |  | 		void Unlock(u8* ptr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	private: | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		u64 size; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		typedef std::map<u8*, u8*>Lockmap; | 
					
						
							|  |  |  | 		Lockmap lockMap; | 
					
						
							|  |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  | 		HANDLE hFile; | 
					
						
							|  |  |  | 		HANDLE hFileMapping; | 
					
						
							|  |  |  | #elif POSIX
 | 
					
						
							|  |  |  | 		int fd; | 
					
						
							|  |  |  | 		typedef std::map<u8*, size_t>Sizemap; | 
					
						
							|  |  |  | 		Sizemap sizeMap; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		int granularity; | 
					
						
							|  |  |  | }; | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CMappedFile::CMappedFile() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  | 	hFile = INVALID_HANDLE_VALUE; | 
					
						
							|  |  |  | 	SYSTEM_INFO info; | 
					
						
							|  |  |  | 	GetSystemInfo(&info); | 
					
						
							|  |  |  | 	granularity = (int)info.dwAllocationGranularity; | 
					
						
							|  |  |  | #elif POSIX
 | 
					
						
							|  |  |  | 	fd = -1; | 
					
						
							|  |  |  | 	granularity = getpagesize(); //sysconf(_SC_PAGE_SIZE);
 | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | CMappedFile::~CMappedFile() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Close(); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool CMappedFile::Open(const char* filename) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	Close(); | 
					
						
							|  |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  | 	hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, 0,   OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (hFile == INVALID_HANDLE_VALUE) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return(false); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	hFileMapping = CreateFileMapping(hFile, 0, PAGE_READONLY, 0, 0, NULL); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	if (hFileMapping == NULL) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		CloseHandle(hFile); | 
					
						
							|  |  |  | 		hFile = 0; | 
					
						
							|  |  |  | 		return(false); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	u32 high = 0; | 
					
						
							|  |  |  | 	u32 low = GetFileSize(hFile, (LPDWORD)&high); | 
					
						
							|  |  |  | 	size = (u64)low | ((u64)high << 32); | 
					
						
							|  |  |  | #elif POSIX
 | 
					
						
							|  |  |  | 	fd   = open(filename, O_RDONLY); | 
					
						
							| 
									
										
										
										
											2008-08-26 11:44:17 +00:00
										 |  |  | 	size = lseek(fd, 0, SEEK_END); | 
					
						
							|  |  |  | 	lseek(fd, 0, SEEK_SET); | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	return(true); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | bool CMappedFile::IsOpen() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  | 	return(hFile != INVALID_HANDLE_VALUE); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif POSIX
 | 
					
						
							|  |  |  | 	return(fd != -1); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | u64 CMappedFile::GetSize() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return(size); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CMappedFile::Close() | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  | 	if (hFile != INVALID_HANDLE_VALUE) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		CloseHandle(hFileMapping); | 
					
						
							|  |  |  | 		CloseHandle(hFile); | 
					
						
							|  |  |  | 		lockMap.clear(); | 
					
						
							|  |  |  | 		hFile = INVALID_HANDLE_VALUE; | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif POSIX
 | 
					
						
							|  |  |  | 	if (fd != -1) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		lockMap.clear(); | 
					
						
							|  |  |  | 		sizeMap.clear(); | 
					
						
							|  |  |  | 		close(fd); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 	fd = -1; | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2008-09-01 12:11:08 +00:00
										 |  |  | u8* CMappedFile::Lock(u64 offset, u64 _size) | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | { | 
					
						
							|  |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  | 	if (hFile != INVALID_HANDLE_VALUE) | 
					
						
							|  |  |  | #elif POSIX
 | 
					
						
							|  |  |  | 	if (fd != -1) | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		u64 realOffset = offset & ~(granularity - 1); | 
					
						
							|  |  |  | 		s64 difference = offset - realOffset; | 
					
						
							| 
									
										
										
										
											2008-09-01 12:11:08 +00:00
										 |  |  | 		u64 fake_size = (difference + _size + granularity - 1) & ~(granularity - 1); | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | #ifdef _WIN32
 | 
					
						
							| 
									
										
										
										
											2008-09-01 12:11:08 +00:00
										 |  |  | 		u8* realPtr = (u8*)MapViewOfFile(hFileMapping, FILE_MAP_READ, (DWORD)(realOffset >> 32), (DWORD)realOffset, (SIZE_T)(_size)); | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | 
 | 
					
						
							|  |  |  | 		if (realPtr == NULL) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			return(NULL); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | #elif POSIX
 | 
					
						
							|  |  |  | 		// TODO
 | 
					
						
							|  |  |  | 		u8* realPtr = (u8*)mmap(0, fake_size, PROT_READ, MAP_PRIVATE, fd, (off_t)realOffset); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (!realPtr) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			PanicAlert("Map Failed"); | 
					
						
							|  |  |  | 			exit(0); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		u8* fakePtr = realPtr + difference; | 
					
						
							|  |  |  | 		//add to map
 | 
					
						
							|  |  |  | 		lockMap[fakePtr] = realPtr; | 
					
						
							|  |  |  | #ifndef _WIN32
 | 
					
						
							| 
									
										
										
										
											2008-09-01 12:11:08 +00:00
										 |  |  | 		sizeMap[fakePtr] = _size + difference; | 
					
						
							| 
									
										
										
										
											2008-07-12 17:40:22 +00:00
										 |  |  | #endif
 | 
					
						
							|  |  |  | 		return(fakePtr); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | 	else | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		return(0); | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | void CMappedFile::Unlock(u8* ptr) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	if (ptr != 0) | 
					
						
							|  |  |  | 	{ | 
					
						
							|  |  |  | 		Lockmap::iterator iter = lockMap.find(ptr); | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 		if (iter != lockMap.end()) | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | #ifdef _WIN32
 | 
					
						
							|  |  |  | 			UnmapViewOfFile((*iter).second); | 
					
						
							|  |  |  | #else
 | 
					
						
							|  |  |  | 			munmap((*iter).second, sizeMap[ptr]); | 
					
						
							|  |  |  | #endif
 | 
					
						
							|  |  |  | 			lockMap.erase(iter); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 		else | 
					
						
							|  |  |  | 		{ | 
					
						
							|  |  |  | 			PanicAlert("CMappedFile : Unlock failed"); | 
					
						
							|  |  |  | 		} | 
					
						
							|  |  |  | 	} | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  | IMappedFile* IMappedFile::CreateMappedFile(void) | 
					
						
							|  |  |  | { | 
					
						
							|  |  |  | 	return(new CMappedFile); | 
					
						
							|  |  |  | } | 
					
						
							|  |  |  | } // end of namespace Common
 |