forked from dolphin-emu/dolphin
		
	git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@566 8ced0084-cf51-0410-be5f-012b33b47a6e
		
			
				
	
	
		
			234 lines
		
	
	
		
			4.3 KiB
		
	
	
	
		
			C++
		
	
	
	
	
	
			
		
		
	
	
			234 lines
		
	
	
		
			4.3 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
 |