forked from dolphin-emu/dolphin
		
	git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@1442 8ced0084-cf51-0410-be5f-012b33b47a6e
		
			
				
	
	
		
			234 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			234 lines
		
	
	
		
			4.0 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
| // 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>
 | |
| #else
 | |
| #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);
 | |
| 	size = lseek(fd, 0, SEEK_END);
 | |
| 	lseek(fd, 0, SEEK_SET);
 | |
| #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
 | |
| }
 | |
| 
 | |
| 
 | |
| u8* CMappedFile::Lock(u64 offset, u64 _size)
 | |
| {
 | |
| #ifdef _WIN32
 | |
| 	if (hFile != INVALID_HANDLE_VALUE)
 | |
| #elif POSIX
 | |
| 	if (fd != -1)
 | |
| #endif
 | |
| 	{
 | |
| 		u64 realOffset = offset & ~(granularity - 1);
 | |
| 		s64 difference = offset - realOffset;
 | |
| 		u64 fake_size = (difference + _size + granularity - 1) & ~(granularity - 1);
 | |
| #ifdef _WIN32
 | |
| 		u8* realPtr = (u8*)MapViewOfFile(hFileMapping, FILE_MAP_READ, (DWORD)(realOffset >> 32), (DWORD)realOffset, (SIZE_T)(_size));
 | |
| 
 | |
| 		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
 | |
| 		sizeMap[fakePtr] = _size + difference;
 | |
| #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::CreateMappedFileDEPRECATED(void)
 | |
| {
 | |
| 	return(new CMappedFile);
 | |
| }
 | |
| } // end of namespace Common
 |